The holders
array in the LiquidationPool
can be maliciously appended to (repeatedly), leading to unusable gas cost for various functions.
NOTE: While in the contest README it does state the known issue of:
No length check for number of stake holders. This could cause a problem throughout contract if there are a high number of stakers
I have still reported this, along with a proof of concept to show how this issue should not be ignored as a griefer can completely disrupt the usability of the liquidation pool contract.
In LiquidationPool::addUniqueHolder
, a unique holder is added to the holders
array.
This private function is called by the external function increasePosition
which can be called by anyone.
A malicious user can call increasePosition
with 1 wei worth of TST (or EUROs) repeatedly from new accounts, adding a new member to holders
each time.
Various functions in the LiquidationPool
contract like distributeFees()
, distributeAssets()
, getStakeTotal()
all involve a for-loop which iterates across and reads from each index of the holders array.
Since holders
is an array stored in storage, it is gas-expensive to read from it.
The gas cost of transacting the previously mentioned functions (distributeFees()
, distributeAssets()
, etc) can be made extremely large, griefing the smart contract.
There is no way to reduce the array size, unless the griefer calls decreasePosition()
from each account to delete the member from the holders
array, so this grief is permanent and can increase in severity over time.
The following proof of concept shows how a griefer can maliciously generate addresses and use them to stake in the liquidationPool.
It then shows how the gas cost for the next new users who call increasePosition()
would be extremely unusable.
Note that this only displays the high gas costs in increasePosition()
, but doesn't show the high gas costs that would be associated with distributeFees()
, distributeAssets()
, etc.
For MockLiquidationPool, slightly adjust LiquidationPool::increasePosition()
by commenting out 2 lines:
Manual Review
Foundry (for Proof of Code)
It is recommended to use a mapping to keep track of the holders, rather than an array. This reduces the gas cost since mappings do not need to be iterated to find a certain piece of data, while arrays do.
However if using an array is preferred, then consider having a higher minimum requirement for creating a new position in increasePosition
(currently 1 wei is the requirement) as it would increase the cost required for griefing, reducing the chance of griefing.
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.