Solidity rounds down in integer division, which can lead to small precision losses that add up over multiple calculations.
This is particularly problematic in contracts dealing with revenue sharing, staking, or rewards distribution, where precision is critical.
Game
In this contract, the allocateShare function calculates a recipient's share based on totalFunds, recipientShares, and totalShares
Look for uneven divisions.
// SPDX-License-Identifier: MIT// Open me in VSCode and really think before opening the hints!// Add @audit tags wherever suspicious// Go to the solidity docs to complete missing knowledge of what's happening here// Solve by drafting a fix!pragmasolidity ^0.8.0;contract SharesCalculationGame {uint256public totalShares;uint256public totalFunds;mapping(address=>uint256) public shares;constructor(uint256_totalShares) { totalShares = _totalShares; }functiondepositFunds() publicpayable { totalFunds += msg.value; }functionallocateShare(address recipient,uint256 recipientShares) public {require(recipientShares <= totalShares,"Not enough shares available");uint256 allocation = (totalFunds * recipientShares) / totalShares;require(allocation <= totalFunds,"Allocation exceeds funds"); shares[recipient] += recipientShares; totalFunds -= allocation; (bool success, ) =payable(recipient).call{value: allocation}("");require(success,"Transfer failed"); }}
Solidity's integer division truncates decimals, which can lead to rounding issues in share calculations.
When totalShares is much larger than recipientShares, or doesn’t divide totalFunds evenly, think about how (totalFunds * recipientShares) / totalShares might round down and lose precision
Examine how repeated calls to allocateShare might cause the total allocated funds to differ from totalFunds, especially in cases where small precision errors accumulate.