You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Missing Maximum Participants Check in buyVotes() and Missing Remove from participants[] in sellVotes().
Summary
The buyVotes() function does not check for maximium value of participants.length.
The sellVotes() function does not remove users who have sold all their votes.
* 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.
* A price floor will be established by Ethos, offering to buy back the new ERC-20 tokens at their final vote price upon graduation,
* ensuring participants don't incur losses due to the transition. Only Ethos, through a designated contract, will be authorized to * graduate markets and withdraw funds to initiate this conversion process. This conversion contract is not yet implemented.
The participants.length will increase continusly.
If the participants.length increase excessively, after the graduation, each holder of TRUST and DISTURST votes may not receives equivalent ERC-20 tokens due to running out of gas.
PoC
ReputationMarket.sol
440: function buyVotes(
uint256profileId,
boolisPositive,
uint256maxVotesToBuy,
uint256minVotesToBuy
) publicpayable whenNotPaused activeMarket(profileId) nonReentrant {
_checkMarketExists(profileId);
// preliminary check to ensure this is enough money to buy the minimum requested votes.
(, , , uint256total) =_calculateBuy(markets[profileId], isPositive, minVotesToBuy);
if (total >msg.value) revertInsufficientFunds();
(
uint256purchaseCostBeforeFees,
uint256protocolFee,
uint256donation,
uint256totalCostIncludingFees
) =_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 affordwhile (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 participantif (!isParticipant[profileId][msg.sender]) {
participants[profileId].push(msg.sender);
isParticipant[profileId][msg.sender] =true;
}
// tally market funds
marketFunds[profileId] += purchaseCostBeforeFees;
// Distribute the feesapplyFees(protocolFee, donation, profileId);
// Calculate and refund remaining fundsuint256 refund =msg.value- totalCostIncludingFees;
if (refund >0) _sendEth(refund);
emitVotesBought(
profileId,
msg.sender,
isPositive,
currentVotesToBuy,
totalCostIncludingFees,
block.timestamp
);
_emitMarketUpdate(profileId);
}
539: function sellVotes(
uint256profileId,
boolisPositive,
uint256votesToSell,
uint256minimumVotePrice
) public whenNotPaused activeMarket(profileId) nonReentrant {
_checkMarketExists(profileId);
(uint256proceedsBeforeFees, uint256protocolFee, uint256proceedsAfterFees) =_calculateSell(
markets[profileId],
profileId,
isPositive,
votesToSell
);
uint256 pricePerVote = votesToSell >0? proceedsBeforeFees / votesToSell : 0;
if (pricePerVote < minimumVotePrice) {
revertSellSlippageLimitExceeded(minimumVotePrice, pricePerVote);
}
markets[profileId].votes[isPositive ? TRUST : DISTRUST] -= votesToSell;
votesOwned[msg.sender][profileId].votes[isPositive ? TRUST : DISTRUST] -= votesToSell;
// tally market funds
marketFunds[profileId] -= proceedsBeforeFees;
// apply protocol feesapplyFees(protocolFee, 0, profileId);
// send the proceeds to the seller_sendEth(proceedsAfterFees);
emitVotesSold(
profileId,
msg.sender,
isPositive,
votesToSell,
proceedsAfterFees,
block.timestamp
);
_emitMarketUpdate(profileId);
}
Mitigation
Consider adding a check for maximium value of paricipants.length and removing users who have sold all their votes.
The text was updated successfully, but these errors were encountered:
Magnificent Tortilla Eel
High
Missing Maximum Participants Check in
buyVotes()
and Missing Remove fromparticipants[]
insellVotes()
.Summary
The
buyVotes()
function does not check for maximium value ofparticipants.length
.The
sellVotes()
function does not remove users who have sold all their votes.Root Cause
https://github.com/sherlock-audit/2024-12-ethos-update/blob/main/ethos/packages/contracts/contracts/ReputationMarket.sol#L440
https://github.com/sherlock-audit/2024-12-ethos-update/blob/main/ethos/packages/contracts/contracts/ReputationMarket.sol#L539
Internal pre-conditions
N/A
External pre-conditions
N/A
Attack Path
N/A
Impact
https://github.com/sherlock-audit/2024-12-ethos-update/blob/main/ethos/packages/contracts/contracts/ReputationMarket.sol#L26-L30
The
participants.length
will increase continusly.If the
participants.length
increase excessively, after the graduation, each holder of TRUST and DISTURST votes may not receives equivalent ERC-20 tokens due to running out of gas.PoC
Mitigation
Consider adding a check for maximium value of paricipants.length and removing users who have sold all their votes.
The text was updated successfully, but these errors were encountered: