AntFleet

Disagreement · 7cad6f1a-anthropic-3

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

solo Opus
repo a7cc2ed7·PR #3·reviewed 1 week ago

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.

Other reviewer

The other reviewer flagged nothing in this file/line range.

Why this didn't post

This finding didn't meet AntFleet's unanimous agreement threshold. Both frontier models review every PR independently; only findings they both flag with the same severity and category are posted to the PR. This one fell through.

read the methodology →