Sparkn

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

Loss of funds for the sponser

Summary

After the conclusion of a contest and the allocation of its funds, there exists a scenario where certain sponsors might inadvertently continue to provide funding for the same contest. This situation arises due to the absence of a preventive mechanism that would prohibit completed contests from receiving further funding. Consequently, this contest, which corresponds to a proxy, could receive additional funding from sponsors in error. As a result, the organizer linked to this contest proxy retains the ability to invoke the "deployProxyAndDistribute" function once more. This action leads to the re-distribution of these funds to supporters who have not contributed to solving any problems on this occasion. It's worth noting that this sequence of events can occur prior to the owner executing the "distributeByOwner" function.
The reason for this timing discrepancy lies in the fact that there exists a waiting period defined as "EXPIRATION_TIME = 7 days" During these 7 days, the owner of the contest must wait before being able to retrieve the trapped funds. Within this timeframe, which spans a week, a malicious organizer could exploit the opportunity to distribute the funds to undeserving recipients. This window of time allows for the re-distribution of funds to occur before the owner's ability to reclaim them via the "distributeByOwner" function comes into play.

Vulnerability Details

Impact

When a completed contest receives funding again from a sponsor by mistake or any other reason, a malicious organizer can distribute these funds before the contest owner has a chance to intervene. This introduces centralisation risks not only for the owner, as was already the case, but also for the organizer.

Tools Used

Foundry

Recommendations

Add code for sponsors to check if the contest corresponding to given proxy address is already completed or not, and even then if sponsors sends funds by mistake, add code for owner to rescue this fund as soon as possible and not wait for "EXPIRATION_TIME = 7 days" or organiser will front-run this opportunity.
For example a mapping "isContestCompleted" can be used to record completed contest and a require function before the "_distribute" call to check if the contest in which distribution and deployment is done not happening again:

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);
//check to watch whether we are reusing a contest by mistake
require(_isContestCompleted(proxy), "Contest can't be used again");
_distribute(proxy, data);
//record the completion of contest
_isContestCompleted(proxy)=true;
return proxy;
} ```
similarly for deployProxyAndDistributeBySignature and deployProxyAndDistributeByOwner.

Support

FAQs

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