Sparkn

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

Organizer can input his own address as winner

Summary

Organizer can input his own address as winner

Vulnerability Details

The docs say

"If a contest is created and funded, there is no way to refund"

but the Organizer can input his address as a winner and get the prize which is like a refund.

When calling ProxyFactory.deployProxyAndDistribute() and subsequently Distributor._distribute() there is no input validation that the Organizer isn't inputting his own address as the winner.

function deployProxyAndDistribute(bytes32 contestId, address implementation, bytes calldata data)
public
returns (address)
{
bytes32 salt = _calculateSalt(msg.sender, contestId, implementation);
if (saltToCloseTime[salt] == 0) revert ProxyFactory__ContestIsNotRegistered();
// can set close time to current time and end it immediately if organizer wish
if (saltToCloseTime[salt] > block.timestamp) revert ProxyFactory__ContestIsNotClosed();
address proxy = _deployProxy(msg.sender, contestId, implementation);
_distribute(proxy, data);
return proxy;
}
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;
}
}

There the Organizer can call ProxyFactory.setContest() to set a contest and then call ProxyFactory.deployProxyAndDistribute() with his own address as winner and max percentage to get a "refund", even though the supporters have worked on the contest.
This is not even a sybil attack as described in the know issues because the malicious Organizer doesn't need to have multiple identities.

Impact

A malicious Organizer can rup pull the protocol and cause users to lose confidence in the protocol.

Tools Used

Manual Review

Recommendations

Add a check to ensure the Organizer address is different from the winner address and is not included in the winner array:

uint256 winnersLength = winners.length; // cache length
for (uint256 i; i < winnersLength;) {
+ if (winners[i] == tx.origin) revert Distributor__OrganizerCannotBeWinner();
uint256 amount = totalAmount * percentages[i] / BASIS_POINTS;
erc20.safeTransfer(winners[i], amount);
unchecked {
++i;
}
}

Support

FAQs

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