Dapper Amber Starfish
Medium
The absence of slippage protection in the sellVotes function will cause an unfair price execution vulnerability for vote sellers as market price fluctuations between transaction submission and execution can result in worse-than-expected trade execution prices.
While Base blockchain's architecture prevents traditional front-running attacks, market prices can still change between when a user submits their transaction and when it gets executed.
The sellVotes function in ReputationMarket contract lacks slippage protection, unlike its buying counterpart. This oversight allows transactions to be executed at potentially unfavorable prices due to natural market movements during the period between transaction submission and execution.
function sellVotes(
uint256 profileId,
bool isPositive,
uint256 amount
) public whenNotPaused activeMarket(profileId) nonReentrant {
_checkMarketExists(profileId);
// calculate the amount of votes to sell and the funds received
(
uint256 votesSold,
uint256 fundsReceived,
,
uint256 protocolFee,
uint256 minVotePrice,
uint256 maxVotePrice
) = _calculateSell(markets[profileId], profileId, isPositive, amount);
- User must have votes to sell in the market
- Market must be active (not graduated)
- Market must exist
No response
- Alice initiates a transaction to sell votes at expected price X
- During the period before Alice's transaction is executed:
- Multiple users make trades
- Market price moves significantly downward
- Alice's transaction gets executed:
- The current market price is now much lower than when Alice submitted
- Alice's votes are sold at this lower price
Financial loss for users due to unfavorable price execution
No response
Add slippage protection to the sellVotes function
function sellVotes(
uint256 profileId,
bool isPositive,
uint256 amount,
uint256 minExpectedFunds, // Add minimum expected funds parameter
) public whenNotPaused activeMarket(profileId) nonReentrant {
...
// Add slippage check
if (fundsReceived < minExpectedFunds) {
revert SlippageLimitExceeded();
}