@@ -7,6 +7,7 @@ pragma solidity 0.8.28;
77
88import { IVotes } from "@openzeppelin/contracts/governance/utils/IVotes.sol " ;
99import { IERC5805 } from "@openzeppelin/contracts/interfaces/IERC5805.sol " ;
10+ import { SafeCast } from "@openzeppelin/contracts/utils/math/SafeCast.sol " ;
1011import {
1112 IERC20Metadata
1213} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol " ;
@@ -242,9 +243,11 @@ contract BondedVotes is IERC5805 {
242243 /// FOLD, plus — under an escrow votes source — the vesting-locked FOLD it cannot escrow. All
243244 /// three are FOLD-denominated and read at the same timepoint.
244245 ///
245- /// `getPastBonded` reverts on a timepoint that has not settled, and it is called before the
246- /// timepoint is narrowed to the clock's width, so the cast in {_lockedVotes} can only ever
247- /// see a timepoint the clock has already reached.
246+ /// Cast through `SafeCast` rather than directly. `getPastBonded` already reverts on a
247+ /// timepoint that has not settled, which leaves nothing wide enough to truncate — but that
248+ /// makes the narrowing safe only because of the order these two lines run in, and only for
249+ /// the history this contract happens to be bound to. Reverting on the narrowing itself keeps
250+ /// the guarantee local to this line, where a reader can check it.
248251 function getPastVotes (
249252 address account ,
250253 uint256 timepoint
@@ -254,7 +257,7 @@ contract BondedVotes is IERC5805 {
254257 return
255258 votesSource.getPastVotes (account, timepoint) +
256259 bonded +
257- _lockedVotes (account, uint64 (timepoint), bonded);
260+ _lockedVotes (account, SafeCast. toUint64 (timepoint), bonded);
258261 }
259262
260263 /// @dev The vesting-locked half of the numerator, netted down by the bond.
0 commit comments