Sparkn

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

Contest reward distribution is vulnerable to a DOS attack

Summary

Any contest reward distribution can suffer DOS of 7 days.

Vulnerability Details

In ProxyFactory.sol deployProxyAndDistribute and deployProxyAndDistributeBySignature deploy the proxy contract before distributing the rewards, due to the use of create2 to deploy the contract on a predicted address, any malicious actor can front-run deployProxyAndDistribute or deployProxyAndDistributeBySignature and deploy a contract on the said address. After that, any call to deployProxyAndDistribute and deployProxyAndDistributeBySignature would fail for the attacked contest, as the functions would be attempting to deploy a contract on an address that already has contract code.
In the developer's comments it is said that * @dev front run is allowed because it will only help the tx sender but this is not true as the organizer would need to wait for 7 days(until the expiration passes) and then request the owner to distribute the stuck funds, as the onlyOwner function distributeByOwner requires the EXPIRATION_TIME of 7 days to have passed before being successfully executed:

function distributeByOwner(
address proxy,
address organizer,
bytes32 contestId,
address implementation,
bytes calldata data
) public onlyOwner {
if (proxy == address(0)) revert ProxyFactory__ProxyAddressCannotBeZero();
bytes32 salt = _calculateSalt(organizer, contestId, implementation);
if (saltToCloseTime[salt] == 0) revert ProxyFactory__ContestIsNotRegistered();
// distribute only when it exists and expired
if (saltToCloseTime[salt] + EXPIRATION_TIME > block.timestamp) revert ProxyFactory__ContestIsNotExpired();
_distribute(proxy, data);
}

Impact

Any contest organizer can be forced to wait for 7 days until they are able to reward the winners and they would be required to request assistance from the contract owner.

Tools Used

Manual review

Recommendations

One recommendation is to check if there is any code on the contract address and if there is not, skiping to the distribute function. This is an effective and not complicated solution but developers need to be aware that this mitigation opens possibilities for another attack. If the deployProxyAndDistribute or deployProxyAndDistributeBySignature functions do not fail if there is an already deployed contract, an ERC777 used as the reward token would allow the contest organizer or a winner that has the organizer's signature to reenter the distribute function in Distributor.sol. A malicious organizer would then be allowed to redistribute the rewards just before they are fully transferred, which would minimize the fees they would have to pay. The last 500 basis points meant to be used as fees would be distributed again to the winners, leaving a small fraction for fees. A mitigation to this is adding a nonReentrant modifier to the distribute function in Distributor.sol.

Support

FAQs

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