use safemath to prevent totalBallots overflow

This patches a vulnerability discovered where someone can pass in
large ballot sizes and cause an overflow to pass the check below
This commit is contained in:
Barry Gitarts 2019-10-30 12:39:34 -04:00
parent ed58fb0873
commit e7a45595cb
2 changed files with 62 additions and 5 deletions

View File

@ -0,0 +1,57 @@
pragma solidity ^0.4.24;
/**
* @title SafeMath
* @dev Unsigned math operations with safety checks that revert on error
*/
library SafeMath {
/**
* @dev Multiplies two unsigned integers, reverts on overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b);
return c;
}
/**
* @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
// Solidity only automatically asserts when dividing by 0
require(b > 0);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend).
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a);
uint256 c = a - b;
return c;
}
/**
* @dev Adds two unsigned integers, reverts on overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a);
return c;
}
}

View File

@ -3,9 +3,11 @@ pragma solidity ^0.4.24;
import "../common/Controlled.sol";
import "../token/MiniMeToken.sol";
import "../rlp/RLPHelper.sol";
import "../math/SafeMath.sol";
contract PollManager is Controlled {
using SafeMath for uint256;
struct Poll {
uint startBlock;
@ -182,7 +184,7 @@ contract PollManager is Controlled {
uint totalBallots = 0;
for(uint8 i = 0; i < _ballots.length; i++){
totalBallots += _ballots[i]; // Use safe math here
totalBallots += totalBallots.add(_ballots[i]);
p.ballots[i][msg.sender] = _ballots[i];
@ -257,7 +259,6 @@ contract PollManager is Controlled {
bool _finalized,
uint _voters,
address _author,
uint _rewards,
uint[100] _tokenTotal,
uint[100] _quadraticVotes,
uint[100] _votersByBallot
@ -276,7 +277,6 @@ contract PollManager is Controlled {
_author = p.author;
_finalized = (!p.canceled) && (block.number >= _endTime);
_voters = p.voters;
_rewards = p.rewards;
for(uint8 i = 0; i < p.numBallots; i++){
_tokenTotal[i] = p.results[i];
@ -337,7 +337,7 @@ contract PollManager is Controlled {
totalVotes += p.results[i];
}
require(token.balanceOf(msg.sender) >= claimerVotes, "Can not claim with less tokens");
uint amount = (p.rewards * claimerVotes) / totalVotes;
uint amount = p.rewards.mul(claimerVotes).div(totalVotes);
p.paidClaims[msg.sender] = true;
require(token.transfer(msg.sender, amount), "Reward token transfer failed");
emit RewardClaimed(_idPoll, msg.sender, amount);
@ -353,7 +353,7 @@ contract PollManager is Controlled {
Poll storage p = _polls[_idPoll];
require(block.number >= p.startBlock && block.timestamp < p.endTime && !p.canceled, "Poll is inactive");
require(token.transferFrom(msg.sender, address(this), _amount), "Failed to transfer tokens in");
p.rewards += amount;
p.rewards += _amount;
emit RewardAdded(_idPoll, msg.sender, _amount);
}