Blacklisted STADIUM_ADDRESS address cause fund stuck in the contract forever
The vulnerability relates to the immutability of `STADIUM_ADDRESS`. If this address is blacklisted by the token used for rewards, the system becomes unable to make transfers, leading to funds being stuck in the contract indefinitely.\\nOwner calls `setContest` with the correct `salt`.\\nThe Organizer sends USDC as rewards to a pre-determined Proxy address.\\n`STADIUM_ADDRESS` is blacklisted by the USDC operator.\\nWhen the contest is closed, the Organizer calls `deployProxyAndDistribute` with the registered `contestId` and `implementation` to deploy a proxy and distribute rewards. However, the call to `Distributor._commissionTransfer` reverts at Line 164 due to the blacklisting.\\nUSDC held at the Proxy contract becomes stuck forever.\\n```\\n// Findings are labeled with '<= FOUND'\\n// File: src/Distributor.sol\\n   function _distribute(address token, address[] memory winners, uint256[] memory percentages, bytes memory data)\\n       // rest of code\\n       _commissionTransfer(erc20);// <= FOUND\\n       // rest of code\\n   }\\n    // rest of code\\n   function _commissionTransfer(IERC20 token) internal {\\n       token.safeTransfer(STADIUM_ADDRESS, token.balanceOf(address(this)));// <= FOUND: Blacklisted STADIUM_ADDRESS address cause fund stuck in the contract forever\\n   }\\n```\\n
It is recommended to allow `STADIUM_ADDRESS` to be updatable by a dedicated admin role to avoid token transfer blacklisting. Moreover, since `STADIUM_ADDRESS` is no longer `immutable`, `storage` collision should be taken into account.
This vulnerability is marked as High severity because a blacklisted `STADIUM_ADDRESS` would lead to funds being locked in the Proxy address permanently. Funds are already held in the Proxy, and the Proxy's `_implementation` cannot be changed once deployed. Even the `ProxyFactory.distributeByOwner()` function cannot rescue the funds due to the revert.
```\\n// Findings are labeled with '<= FOUND'\\n// File: src/Distributor.sol\\n   function _distribute(address token, address[] memory winners, uint256[] memory percentages, bytes memory data)\\n       // rest of code\\n       _commissionTransfer(erc20);// <= FOUND\\n       // rest of code\\n   }\\n    // rest of code\\n   function _commissionTransfer(IERC20 token) internal {\\n       token.safeTransfer(STADIUM_ADDRESS, token.balanceOf(address(this)));// <= FOUND: Blacklisted STADIUM_ADDRESS address cause fund stuck in the contract forever\\n   }\\n```\\n