Sparkn

CodeFox Inc.
DeFiFoundryProxy
15,000 USDC
View results
Submission Details
Severity: low
Valid

[H-03] Duplicate Addresses in Winners `address[]` Could Lead to Unfairly Distributed Prize Pool

Summary

The organizer calling to distribute the balance of Proxy.sol could enter a duplicate address which would lead to unfair distribution of rewards.

Vulnerability Details

Consider the following scenario:

  1. There are 3 supporters that come up with a solution to a contest

  2. The organizer decides to split the prize pool into 3 equal parts of ~31.66% (we also take into account the 5% protocol fee)

  3. The organizer calls deployProxyAndDistribute and enters one of the participants' address twice

  4. There are no checks in the _distribute function inside of Distribute.sol to compare if 2 of the values in the array are a duplicate address

  5. The participants take ~63.32%, ~31.66% and 0% respectively

In this scenario one of the participants is left without reward since they were distributed unfairly.

We can take a closer look at the _distribute function inside Distributor.sol to highlight there are no checks for duplicate addresses:

function _distribute(address token, address[] memory winners, uint256[] memory percentages, bytes memory data)
internal
{
// token address input check
if (token == address(0)) revert Distributor__NoZeroAddress();
if (!_isWhiteListed(token)) {
revert Distributor__InvalidTokenAddress();
}
// winners and percentages input check
if (winners.length == 0 || winners.length != percentages.length) revert Distributor__MismatchedArrays();
uint256 percentagesLength = percentages.length;
uint256 totalPercentage;
for (uint256 i; i < percentagesLength;) {
totalPercentage += percentages[i];
unchecked {
++i;
}
}
// check if totalPercentage is correct
if (totalPercentage != (10000 - COMMISSION_FEE)) {
revert Distributor__MismatchedPercentages();
}
IERC20 erc20 = IERC20(token);
uint256 totalAmount = erc20.balanceOf(address(this));
// if there is no token to distribute, then revert
if (totalAmount == 0) revert Distributor__NoTokenToDistribute();
uint256 winnersLength = winners.length; // cache length
for (uint256 i; i < winnersLength;) {
uint256 amount = totalAmount * percentages[i] / BASIS_POINTS;
erc20.safeTransfer(winners[i], amount); // @audit no checks to verify off-chain with on-chain info so we can just distribute tokens to whatever address we like (including ours)
unchecked {
++i;
}
}
// send commission fee as well as all the remaining tokens to STADIUM_ADDRESS to avoid dust remaining
_commissionTransfer(erc20);
emit Distributed(token, winners, percentages, data);
}

Impact

The impact is unfair distribution of rewards, one participant gets more than they should and another is left with no rewards. This would lead to a High Severity issue if the prize pool for a given contest is large.

Tools Used

VSCode, Manual Review

Recommendations

Check inside the _distribute function to compare the values input in the winners array and revert if duplicate addresses exist.

Another possible mitigation is to revert if participant % == 0. Although this does not fix the root caues of the issue which is duplicate addresses inside the winners[].

Support

FAQs

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