ProxyFactory.distributeByOwner()
should have a check if proxy is matching with organizer and contestId.
If wrong proxy parameter is used, it would lead to wrong prize distribution.
Vulnerability Details
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();
if (saltToCloseTime[salt] + EXPIRATION_TIME > block.timestamp) revert ProxyFactory__ContestIsNotExpired();
_distribute(proxy, data);
}
Impact
Wrong proxy prize money can be used to distributed prize.
Tools Used
Manual Review
Recommendations
It should keep track of proxy address with matching salt when deploying proxy.
+ mapping (address => uint256) proxySalt;
function _deployProxy(address organizer, bytes32 contestId, address implementation) internal returns (address) {
bytes32 salt = _calculateSalt(organizer, contestId, implementation);
address proxy = address(new Proxy{salt: salt}(implementation));
+ proxySalt[salt] = proxy;
return proxy;
}
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();
if (saltToCloseTime[salt] + EXPIRATION_TIME > block.timestamp) revert ProxyFactory__ContestIsNotExpired();
+ if (proxySalt[proxy] != salt) revert ProxyFactory__WrongProxyAddress;
_distribute(proxy, data);
}