If a contest involves a lot of winners, the Distributor.sol:_distribute
function will likely fail to execute successfully due to running out of gas.
The existing Distributor.sol:_distribute
function lacks optimization to work with a large number of winners and varying percentages. The tests focus on scenarios with a maximum of 3 winners. However, real contests could involve a significantly larger number of winners. In such instances, the current implementation of _distribute
is prone to out of gas error due to its structure involving two for loops iterating the entire winners array.
Here's an example of a Proof of Concept for a contest featuring 9500 winners (the most extreme scenario). However, a similar issue can arise even with a lower number of winners.
Add the following test to the ProxyFactoryTest.t.sol
file:
Run the test with 30 million gas limit per block (Ethereum current block gas limit):
forge test --gas-limit 30000000
The result, the transaction with 9500 winners will fail, due to not enough gas:
Distributing prizes for contests with a large number of winners would be impossible.
Manual Review
Optimize the Distributor.sol:_distribute
function as I mentioned in the Discord Message.
No need for dual iterations through the arrays (as their lengths match). Merge the loops responsible for percentage calculation and money distribution to winners. Following the execution of this consolidated loop, perform the percentages check, and if an error exist, revert the entire transaction. Given the transaction's atomic nature, all transfers will be reversed, resulting in substantial gas savings.
When dealing with many winners, consider enabling the division of the distribution process into multiple transactions. This approach overcomes the gas limit constraint that could prevent the prize distribution process for a contest. While implementing this may introduce added complexity to the code, it guarantees that regardless of the number of winners, prize distribution remains feasible.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.