Main Honeysuckle Tarantula
Medium
Consider the buyVotes
function. Specifically its internal call to _calculateBuy
.
function _calculateBuy(
Market memory market,
bool isPositive,
uint256 funds
)
private
view
returns (
uint256 votesBought,
uint256 fundsPaid,
uint256 newVotePrice,
uint256 protocolFee,
uint256 donation,
uint256 minVotePrice,
uint256 maxVotePrice
)
{
uint256 fundsAvailable;
(fundsAvailable, protocolFee, donation) = previewFees(funds, true);
uint256 votePrice = _calcVotePrice(market, isPositive);
uint256 minPrice = votePrice;
uint256 maxPrice;
if (fundsAvailable < votePrice) {
revert InsufficientFunds();
}
while (fundsAvailable >= votePrice) {
fundsAvailable -= votePrice;
fundsPaid += votePrice;
votesBought++;
market.votes[isPositive ? TRUST : DISTRUST] += 1;
votePrice = _calcVotePrice(market, isPositive);
}
fundsPaid += protocolFee + donation;
maxPrice = votePrice;
return (votesBought, fundsPaid, votePrice, protocolFee, donation, minPrice, maxPrice);
}
The previewFees function counts the commission that the user will pay for the purchase. However, the funds - passed to previewFees - is msg.value attached to the call.
Thus, the amount of commission the user will pay depends only on the msg.value he attaches to the message, not on the amount he spends on the purchase.
That is, either the user tries to minimise the msg.value and risks not buying the vote because of slippage, or he doesn't minimise it and overpays the commission.
Judging by the sponsor's discord message, it is important to the protocol that users do not overpay the commission, I will now show that user losses can be significant.
For simplicity, let's assume that 1 vote costs 90 ETH. The user wants to buy exactly 1 vote. Protocol commission 5%, donation 5%.
So, if msg.value is in [100; 200] - user will get exactly 1 share, but will pay different amount of fee.
msg.value = 100. ProtocolFee = 5, Donation = 5. Price = 90. TotalCost = 100
msg.value = 150. ProtocolFee = 7.5, Donation = 7.5. Price = 90. TotalCost = 105
msg.value = 200. ProtocolFee = 10, Donation = 10, Price = 90. TotalCost = 110
The user overpays up to 10% in the worst case.
The purchase commission depends on the msg.value attached, not the money spent. Msg.value may be inflated by the buyer due to slippage, but in this case he will overpay the protocol.
No response
No response
No response
The user loses funds through no fault of their own (if they specify an accurate msg.value, they probably won't buy because of slippage)
No response
Calculate fees from spend funds, not from msg.value