distributeToAllHolders() function performs reward distribution to the entire holders array in a single transaction. File: LiquidInfrastructureERC20.sol#distribute
function distribute(uint256 numDistributions) public nonReentrant {
require(numDistributions > 0, "must process at least 1 distribution");
If there are a large number of token holders (e.g. 10,000+), attempting to distribute to all in one tx could easily exceed the block gas limit.
This would trigger an out-of-gas that leaves the contract in a locked state for distribution.
Recommendation:Iteratively distribute rewards in batches controlled via an input parameter.
distribute() Input
While distribute() takes a numDistributions parameter to control iteration count, there is no max cap:
function distribute(uint256 numDistributions) public nonReentrant {
require(numDistributions > 0, "must process at least 1 distribution");
An excessively high input value could similarly trigger out-of-gas exceptions.
Recommendation: Enforce upper bound check on input parameter.
Other Vectors
The only state change that cannot be "rolled back" is if LastDistribution is updated but an exception happens before _endDistribution(). This would indefinitely lock distribution and allow DoS.
Tools Used
Vs Code
Recommended Mitigation Steps
The main risks relate to gas limits during distribution. Capping input ranges provides protection.
Lines of code
https://github.com/code-423n4/2024-02-althea-liquid-infrastructure/blob/bd6ee47162368e1999a0a5b8b17b701347cf9a7d/liquid-infrastructure/contracts/LiquidInfrastructureERC20.sol#L198-L199
Vulnerability details
Impact
distributeToAllHolders()
function performs reward distribution to the entireholders
array in a single transaction. File: LiquidInfrastructureERC20.sol#distributeIf there are a large number of token holders (e.g. 10,000+), attempting to distribute to all in one tx could easily exceed the block gas limit.
This would trigger an out-of-gas that leaves the contract in a locked state for distribution.
Recommendation:Iteratively distribute rewards in batches controlled via an input parameter.
distribute() Input
While
distribute()
takes anumDistributions
parameter to control iteration count, there is no max cap:An excessively high input value could similarly trigger out-of-gas exceptions.
Recommendation: Enforce upper bound check on input parameter.
Other Vectors
The only state change that cannot be "rolled back" is if
LastDistribution
is updated but an exception happens before_endDistribution()
. This would indefinitely lock distribution and allow DoS.Tools Used
Vs Code
Recommended Mitigation Steps
The main risks relate to gas limits during distribution. Capping input ranges provides protection.
Assessed type
DoS