mirror of
https://github.com/status-im/snt-voting.git
synced 2025-02-23 23:58:13 +00:00
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:
parent
ed58fb0873
commit
e7a45595cb
57
contracts/math/SafeMath.sol
Normal file
57
contracts/math/SafeMath.sol
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -3,9 +3,11 @@ pragma solidity ^0.4.24;
|
|||||||
import "../common/Controlled.sol";
|
import "../common/Controlled.sol";
|
||||||
import "../token/MiniMeToken.sol";
|
import "../token/MiniMeToken.sol";
|
||||||
import "../rlp/RLPHelper.sol";
|
import "../rlp/RLPHelper.sol";
|
||||||
|
import "../math/SafeMath.sol";
|
||||||
|
|
||||||
|
|
||||||
contract PollManager is Controlled {
|
contract PollManager is Controlled {
|
||||||
|
using SafeMath for uint256;
|
||||||
|
|
||||||
struct Poll {
|
struct Poll {
|
||||||
uint startBlock;
|
uint startBlock;
|
||||||
@ -182,7 +184,7 @@ contract PollManager is Controlled {
|
|||||||
|
|
||||||
uint totalBallots = 0;
|
uint totalBallots = 0;
|
||||||
for(uint8 i = 0; i < _ballots.length; i++){
|
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];
|
p.ballots[i][msg.sender] = _ballots[i];
|
||||||
|
|
||||||
@ -257,7 +259,6 @@ contract PollManager is Controlled {
|
|||||||
bool _finalized,
|
bool _finalized,
|
||||||
uint _voters,
|
uint _voters,
|
||||||
address _author,
|
address _author,
|
||||||
uint _rewards,
|
|
||||||
uint[100] _tokenTotal,
|
uint[100] _tokenTotal,
|
||||||
uint[100] _quadraticVotes,
|
uint[100] _quadraticVotes,
|
||||||
uint[100] _votersByBallot
|
uint[100] _votersByBallot
|
||||||
@ -276,7 +277,6 @@ contract PollManager is Controlled {
|
|||||||
_author = p.author;
|
_author = p.author;
|
||||||
_finalized = (!p.canceled) && (block.number >= _endTime);
|
_finalized = (!p.canceled) && (block.number >= _endTime);
|
||||||
_voters = p.voters;
|
_voters = p.voters;
|
||||||
_rewards = p.rewards;
|
|
||||||
|
|
||||||
for(uint8 i = 0; i < p.numBallots; i++){
|
for(uint8 i = 0; i < p.numBallots; i++){
|
||||||
_tokenTotal[i] = p.results[i];
|
_tokenTotal[i] = p.results[i];
|
||||||
@ -337,7 +337,7 @@ contract PollManager is Controlled {
|
|||||||
totalVotes += p.results[i];
|
totalVotes += p.results[i];
|
||||||
}
|
}
|
||||||
require(token.balanceOf(msg.sender) >= claimerVotes, "Can not claim with less tokens");
|
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;
|
p.paidClaims[msg.sender] = true;
|
||||||
require(token.transfer(msg.sender, amount), "Reward token transfer failed");
|
require(token.transfer(msg.sender, amount), "Reward token transfer failed");
|
||||||
emit RewardClaimed(_idPoll, msg.sender, amount);
|
emit RewardClaimed(_idPoll, msg.sender, amount);
|
||||||
@ -353,7 +353,7 @@ contract PollManager is Controlled {
|
|||||||
Poll storage p = _polls[_idPoll];
|
Poll storage p = _polls[_idPoll];
|
||||||
require(block.number >= p.startBlock && block.timestamp < p.endTime && !p.canceled, "Poll is inactive");
|
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");
|
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);
|
emit RewardAdded(_idPoll, msg.sender, _amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user