Urban Obsidian Jay
High
In ReputationMarket.sol::buyVotes()
, there is no check for minVotesToBuy
, maxVotesToBuy
, and currentVotesToBuy
.
N/A
N/A
Malicious users may call the buyVotes()
function with minVotesToBuy = maxVotesToBuy = 0
.
As a result, participants[profileId].length
could be increased unintentionally.
- Graduation: the intent is that upon graduation, each holder of trust and distrust votes receives equivalent ERC-20 tokens
- representing their position. These tokens will be freely tradable, without the reciprocal pricing mechanism of this contract.
If the length of participants is increased unintentionally, after graduation, each holder of trust and distrust votes may not receive their ERC-20 tokens due to running out of gas.
ReputationMarket.sol
function buyVotes(
uint256 profileId,
bool isPositive,
uint256 maxVotesToBuy,
uint256 minVotesToBuy
) public payable whenNotPaused activeMarket(profileId) nonReentrant {
_checkMarketExists(profileId);
// preliminary check to ensure this is enough money to buy the minimum requested votes.
(, , , uint256 total) = _calculateBuy(markets[profileId], isPositive, minVotesToBuy);
if (total > msg.value) revert InsufficientFunds();
(
uint256 purchaseCostBeforeFees,
uint256 protocolFee,
uint256 donation,
uint256 totalCostIncludingFees
) = _calculateBuy(markets[profileId], isPositive, maxVotesToBuy);
uint256 currentVotesToBuy = maxVotesToBuy;
// if the cost is greater than the maximum votes to buy,
// decrement vote count and recalculate until we identify the max number of votes they can afford
while (totalCostIncludingFees > msg.value) {
currentVotesToBuy--;
(purchaseCostBeforeFees, protocolFee, donation, totalCostIncludingFees) = _calculateBuy(
markets[profileId],
isPositive,
currentVotesToBuy
);
}
// Update market state
markets[profileId].votes[isPositive ? TRUST : DISTRUST] += currentVotesToBuy;
votesOwned[msg.sender][profileId].votes[isPositive ? TRUST : DISTRUST] += currentVotesToBuy;
// Add buyer to participants if not already a participant
474: if (!isParticipant[profileId][msg.sender]) {
participants[profileId].push(msg.sender);
isParticipant[profileId][msg.sender] = true;
}
// tally market funds
marketFunds[profileId] += purchaseCostBeforeFees;
// Distribute the fees
applyFees(protocolFee, donation, profileId);
// Calculate and refund remaining funds
uint256 refund = msg.value - totalCostIncludingFees;
if (refund > 0) _sendEth(refund);
emit VotesBought(
profileId,
msg.sender,
isPositive,
currentVotesToBuy,
totalCostIncludingFees,
block.timestamp
);
_emitMarketUpdate(profileId);
}
+ require(minVotesToBuy <= maxVotesToBuy,"")
+ if (currentVotesToBuy > 0)
474: if (!isParticipant[profileId][msg.sender]) {
participants[profileId].push(msg.sender);
isParticipant[profileId][msg.sender] = true;
}