DatingDapp

First Flight #33
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Severity: low
Invalid

Rounding Issue in Fee and Reward Calculation (LikeRegistry Contract)

Summary

The matchRewards function in the LikeRegistry contract introduces a rounding issue when calculating fees and rewards. Solidity’s integer division truncates decimal values, which can result in minor discrepancies that accumulate over multiple transactions. This issue could lead to unintended fund misallocations, where either:

  • The contract collects slightly less in fees than expected, leading to inconsistencies.

  • The rewards calculation leads to imbalanced fund distribution.

Affected Code (matchRewards Function)

function matchRewards(address from, address to) internal {
uint256 matchUserOne = userBalances[from];
uint256 matchUserTwo = userBalances[to];
userBalances[from] = 0;
userBalances[to] = 0;
uint256 totalRewards = matchUserOne + matchUserTwo;
uint256 matchingFees = (totalRewards * FIXEDFEE) / 100; // Rounding issue occurs here
uint256 rewards = totalRewards - matchingFees;
totalFees += matchingFees;
// Deploy a MultiSig contract for the matched users
MultiSigWallet multiSigWallet = new MultiSigWallet(from, to);
// Send ETH to the deployed multisig wallet
(bool success,) = payable(address(multiSigWallet)).call{value: rewards}("");
require(success, "Transfer failed");
}

Impact

  • Loss of Precision: Due to integer division, small amounts of ETH could be misallocated.

  • Accumulated Discrepancy: Over multiple transactions, these rounding errors could result in an unintended shift of funds.

  • Potential Inconsistencies: The contract might collect slightly less in fees or allocate incorrect rewards to users.

Steps to Reproduce (Proof of Concept - PoC)

  1. Set FIXEDFEE = 10 (10% fee).

  2. Assume userBalances[from] = 123 and userBalances[to] = 0.

  3. The expected fee should be 123 * 10 / 100 = 12.3, but Solidity rounds this down to 12, losing 0.3 ETH.

  4. The rewards calculation results in 123 - 12 = 111 instead of 110.7, leading to an imbalance.

PoC Code (Using Foundry)

function testRoundingIssue() public {
uint256 matchUserOne = 123;
uint256 matchUserTwo = 0;
uint256 totalRewards = matchUserOne + matchUserTwo;
// Calculate matchingFees with integer division
uint256 matchingFees = (totalRewards * FIXEDFEE) / 100;
// Verify rounding issue
assertEq(matchingFees, 12, "Matching fees should be 12");
assertEq(totalRewards - matchingFees, 111, "Rewards should be 111");
}

Recommended Fix

Use a scaling factor (e.g., 1e18) before performing division to minimize rounding errors:

function matchRewards(address from, address to) internal {
uint256 matchUserOne = userBalances\[from];
uint256 matchUserTwo = userBalances\[to];
userBalances\[from] = 0;
userBalances\[to] = 0;
uint256 totalRewards = matchUserOne + matchUserTwo;
// Apply a scaling factor to preserve precision
uint256 matchingFees = (totalRewards * FIXEDFEE * 1e18) / (100 * 1e18);
uint256 rewards = totalRewards - matchingFees;
totalFees += matchingFees;
MultiSigWallet multiSigWallet = new MultiSigWallet(from, to);
(bool success,) = payable(address(multiSigWallet)).call{value: rewards}("");
require(success, "Transfer failed");
}

Severity

  • LOW: While the issue does not completely lock funds, it results in incorrect fund allocation over time.

Conclusion

The rounding issue in matchRewards leads to minor misallocations of ETH, which can accumulate over multiple transactions. Implementing a scaling factor or proper rounding correction will prevent these inconsistencies and ensure precise calculations.

Updates

Appeal created

n0kto Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

Informational or Gas

Please read the CodeHawks documentation to know which submissions are valid. If you disagree, provide a coded PoC and explain the real likelyhood and the detailed impact on the mainnet without any supposition (if, it could, etc) to prove your point.

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.