Choose a precision factor large enough to handle small decimal values:
// Use higher precision instead of standard 1e18
uint256 private constant PRECISION = 1e24;
Always multiply before dividing to prevent precision loss:
// Incorrect - Precision loss due to early division
uint256 result = (amount * rate) / precision;
// Correct - Multiply by precision factor first, then divide
uint256 result = (amount * rate * PRECISION) / (precision * PRECISION);
Apply the same precision calculation pattern throughout the contract:
// Reward calculation example
uint256 rewardPerShare = (reward * PRECISION * PRECISION) / (totalStaked * PRECISION);
uint256 pending = (userStakeAmount * accRewardPerShare * PRECISION) / (PRECISION * PRECISION);
contract Example {
uint256 private constant PRECISION = 1e24;
function calculateReward(uint256 amount, uint256 rate) public pure returns (uint256) {
// First multiply by precision factors
uint256 preciseAmount = amount * PRECISION;
uint256 preciseRate = rate * PRECISION;
// Then perform division
return (preciseAmount * preciseRate) / (PRECISION * PRECISION);
}
}