Opus finding
CloneERC20.mintInflation drops sub-year residual when no full year has elapsed since lastMintTimestamp, but updates `currentYearStart` only inside the loop — works correctly; however `updateMintRate` bypasses `lastMintTimestamp` update when no inflation is accrued
mediumbugmedium
- src/tokens/CloneERC20.sol:196-216
- src/tokens/CloneERC20.sol:162-195
`updateMintRate` calls `mintInflation` to settle accrued inflation at the old rate before changing the rate. But `mintInflation` reverts if `mintableAmount == 0` (e.g., when `block.timestamp == lastMintTimestamp` or, due to integer truncation, when the elapsed time is too small for the rounding to produce any mintable tokens, e.g. very small supply or rate). When such a revert occurs in the inner call, the entire `updateMintRate` transaction reverts. More subtly, when `mintableAmount` rounds to 0 but time has elapsed, the owner has no way to update the rate without first donating supply or waiting — minor griefing risk. The required check `(block.timestamp - lastMintTimestamp) != 0` does not guard against the rounding-to-zero case. A safer pattern is to settle inflation without reverting when accrual is zero.
Recommendation
Make `mintInflation` callable internally without reverting on zero (split into `_accrueInflation` that returns mintableAmount and only reverts when called externally with zero). Or in `updateMintRate`, update `lastMintTimestamp = block.timestamp` after the rate change to capture residual time at new rate, without forcing a mint.