22
33pragma solidity 0.8.16 ;
44
5- import { IERC20 } from "@oz/token/ERC20/IERC20.sol " ;
6- import { SafeERC20 } from "@oz/token/ERC20/utils/SafeERC20.sol " ;
5+ import { IERC20 } from "@oz/token/ERC20/IERC20.sol " ;
6+ import { SafeCast } from "@oz/utils/math/SafeCast.sol " ;
7+ import { SafeERC20 } from "@oz/token/ERC20/utils/SafeERC20.sol " ;
78
89import { Funding } from "./Funding.sol " ;
910
@@ -128,7 +129,7 @@ abstract contract StandardFunding is Funding, IStandardFunding {
128129 }
129130
130131 // set the distribution period to start at the current block
131- uint48 startBlock = uint48 (block .number );
132+ uint48 startBlock = SafeCast. toUint48 (block .number );
132133 uint48 endBlock = startBlock + DISTRIBUTION_PERIOD_LENGTH;
133134
134135 // set new value for currentDistributionId
@@ -140,7 +141,7 @@ abstract contract StandardFunding is Funding, IStandardFunding {
140141 newDistributionPeriod.startBlock = startBlock;
141142 newDistributionPeriod.endBlock = endBlock;
142143 uint256 gbc = Maths.wmul (treasury, GLOBAL_BUDGET_CONSTRAINT);
143- newDistributionPeriod.fundsAvailable = uint128 (gbc);
144+ newDistributionPeriod.fundsAvailable = SafeCast. toUint128 (gbc);
144145
145146 // decrease the treasury by the amount that is held for allocation in the new distribution period
146147 treasury -= gbc;
@@ -180,6 +181,7 @@ abstract contract StandardFunding is Funding, IStandardFunding {
180181
181182 /**
182183 * @notice Updates Treasury with surplus funds from distribution.
184+ * @dev Counters incremented in an unchecked block due to being bounded by array length of at most 10.
183185 * @param distributionId_ distribution Id of updating distribution
184186 */
185187 function _updateTreasury (
@@ -319,7 +321,7 @@ abstract contract StandardFunding is Funding, IStandardFunding {
319321 if (proposal.fundingVotesReceived < 0 ) return false ;
320322
321323 // update counters
322- sum += uint128 (proposal.fundingVotesReceived);
324+ sum += uint128 (proposal.fundingVotesReceived); // since we are converting from int128 to uint128, we can safely assume that the value will not overflow
323325 totalTokensRequested += proposal.tokensRequested;
324326
325327 // check if slate of proposals exceeded budget constraint ( 90% of GBC )
@@ -452,14 +454,15 @@ abstract contract StandardFunding is Funding, IStandardFunding {
452454 /**
453455 * @notice Calculates the sum of funding votes allocated to a list of proposals.
454456 * @dev Only iterates through a maximum of 10 proposals that made it through the screening round.
455- * @dev Counters incremented in an unchecked block due to being bounded by array length.
457+ * @dev Counters incremented in an unchecked block due to being bounded by array length of at most 10 .
456458 * @param proposalIdSubset_ Array of proposal Ids to sum.
457459 * @return sum_ The sum of the funding votes across the given proposals.
458460 */
459461 function _sumProposalFundingVotes (
460462 uint256 [] memory proposalIdSubset_
461463 ) internal view returns (uint128 sum_ ) {
462464 for (uint i = 0 ; i < proposalIdSubset_.length ;) {
465+ // since we are converting from int128 to uint128, we can safely assume that the value will not overflow
463466 sum_ += uint128 (standardFundingProposals[proposalIdSubset_[i]].fundingVotesReceived);
464467
465468 unchecked { ++ i; }
@@ -505,6 +508,7 @@ abstract contract StandardFunding is Funding, IStandardFunding {
505508
506509 // voter had already cast a funding vote on this proposal
507510 if (voteCastIndex != - 1 ) {
511+ // since we are converting from int256 to uint256, we can safely assume that the value will not overflow
508512 FundingVoteParams storage existingVote = votesCast[uint256 (voteCastIndex)];
509513
510514 // can't change the direction of a previous vote
@@ -524,7 +528,10 @@ abstract contract StandardFunding is Funding, IStandardFunding {
524528 }
525529
526530 // calculate the cumulative cost of all votes made by the voter
527- uint128 cumulativeVotePowerUsed = uint128 (_sumSquareOfVotesCast (votesCast));
531+ // and check that attempted votes cast doesn't overflow uint128
532+ uint256 sumOfTheSquareOfVotesCast = _sumSquareOfVotesCast (votesCast);
533+ if (sumOfTheSquareOfVotesCast > type (uint128 ).max) revert InsufficientVotingPower ();
534+ uint128 cumulativeVotePowerUsed = SafeCast.toUint128 (sumOfTheSquareOfVotesCast);
528535
529536 // check that the voter has enough voting power remaining to cast the vote
530537 if (cumulativeVotePowerUsed > votingPower) revert InsufficientVotingPower ();
@@ -533,17 +540,17 @@ abstract contract StandardFunding is Funding, IStandardFunding {
533540 voter_.remainingVotingPower = votingPower - cumulativeVotePowerUsed;
534541
535542 // calculate the change in voting power used by the voter in this vote in order to accurately track the total voting power used in the funding stage
543+ // since we are moving from uint128 to uint256, we can safely assume that the value will not overflow
536544 uint256 incrementalVotingPowerUsed = uint256 (cumulativeVotePowerUsed - voterPowerUsedPreVote);
537545
538546 // update accumulator for total voting power used in the funding stage in order to calculate delegate rewards
539547 currentDistribution_.fundingVotePowerCast += incrementalVotingPowerUsed;
540548
541549 // update proposal vote tracking
542- proposal_.fundingVotesReceived += int128 (voteParams_.votesUsed);
550+ proposal_.fundingVotesReceived += SafeCast. toInt128 (voteParams_.votesUsed);
543551
544- // the incremental additional votes cast on the proposal
545- // used as a return value and emit value
546- incrementalVotesUsed_ = uint256 (Maths.abs (voteParams_.votesUsed));
552+ // the incremental additional votes cast on the proposal to be used as a return value and emit value
553+ incrementalVotesUsed_ = SafeCast.toUint256 (Maths.abs (voteParams_.votesUsed));
547554
548555 // emit VoteCast instead of VoteCastWithParams to maintain compatibility with Tally
549556 // emits the amount of incremental votes cast for the proposal, not the voting power cost or total votes on a proposal
@@ -576,7 +583,7 @@ abstract contract StandardFunding is Funding, IStandardFunding {
576583 uint256 proposalId = proposal_.proposalId;
577584
578585 // update proposal votes counter
579- proposal_.votesReceived += uint128 (votes_);
586+ proposal_.votesReceived += SafeCast. toUint128 (votes_);
580587
581588 // check if proposal was already screened
582589 int indexInArray = _findProposalIndex (proposalId, currentTopTenProposals);
@@ -659,6 +666,7 @@ abstract contract StandardFunding is Funding, IStandardFunding {
659666 ) internal pure returns (int256 index_ ) {
660667 index_ = - 1 ; // default value indicating proposalId not in the array
661668
669+ // since we are converting from uint256 to int256, we can safely assume that the value will not overflow
662670 int256 numVotesCast = int256 (voteParams_.length );
663671 for (int256 i = 0 ; i < numVotesCast; ) {
664672 //slither-disable-next-line incorrect-equality
@@ -675,6 +683,7 @@ abstract contract StandardFunding is Funding, IStandardFunding {
675683 * @notice Sort the 10 proposals which will make it through screening and move on to the funding round.
676684 * @dev Implements the descending insertion sort algorithm.
677685 * @dev Counters incremented in an unchecked block due to being bounded by array length.
686+ * @dev Since we are converting from int256 to uint256, we can safely assume that the values will not overflow.
678687 * @param arr_ The array of proposals to sort by votes recieved.
679688 */
680689 function _insertionSortProposalsByVotes (
@@ -713,7 +722,7 @@ abstract contract StandardFunding is Funding, IStandardFunding {
713722 uint256 numVotesCast = votesCast_.length ;
714723
715724 for (uint256 i = 0 ; i < numVotesCast; ) {
716- votesCastSumSquared_ += Maths.wpow (uint256 (Maths.abs (votesCast_[i].votesUsed)), 2 );
725+ votesCastSumSquared_ += Maths.wpow (SafeCast. toUint256 (Maths.abs (votesCast_[i].votesUsed)), 2 );
717726
718727 unchecked { ++ i; }
719728 }
0 commit comments