The entire system is designed to enable Smart Vault liquidation, which cannot be carried out without the following steps:
To achieve this, developers chose to use arrays and mandate operations on each element of these arrays whenever a liquidation occurs.
Furthermore, modifying these arrays is permissionless through LiquidationPool.increasePosition. This opens up two similar vector attacks:
DOS through liquidations: Positions decrease and increase, causing the number of holders to reach the block gas limit each time consolidatePendingStakes is called. This issue has been acknowledged but remains unfixed.
Another DOS scenario through liquidations: Positions decrease and increase, leading to the block gas limit being reached whenever consolidatePendingStakes is called due to the number of pending stakes. This issue has not been acknowledged.
Both issues are easily triggered, with the first one by creating multiple addresses and positions, and the second one by increasing a position multiple times
DOS through liquidations: Positions decrease and increase when the number of holders forces reaching the block gas limit every time consolidatePendingStakes is called. Currently acknowledged but not fixed.
DOS through liquidations: Positions decrease and increase when the number of pending stakes forces reaching the block gas limit every time consolidatePendingStakes is called. Currently NOT acknowledged.
Alice possesses a vault holding 1 million EUR, which currently lacks sufficient collateral. Someone attempts to call LiquidationPoolManager::runLiquidation(AliceValutId), but Alice anticipates this action and front-runs it by increasing her position multiple times with 1 wei EUROS. This causes a dramatic increase in the number of pending stakes. Consequently, when LiquidationPoolManager::runLiquidation(AliceValutId) is triggered, the transaction gets reverted due to reaching the gas limit.
Protocol permanent freeze
Allow only one pending stake per address. When a user wants to increase their position and there's an existing pending stake, their values get incremented, and the deadline gets updated.
Delegate position consolidation to users.
Conduct fee distribution, considering only consolidated positions.
Design an epoch system for asset and fee distribution, opting for X epochs consolidation instead of the standard 24 hours.
To illustrate the proposed solution, let's consider the following assumptions:
Epochs are set at 24 hours each.
A holder can consolidate their position only after the completion of the next epoch, and it will be considered consolidated in the subsequent epoch.
Rewards and fees are calculated based on epochs.
There exists a state variable that accounts for the current total stake.
To receive rewards from fees and asset distributions during an epoch, a holder must maintain their position from the start of the epoch until its completion.
Now, let's examine the following scenarios:
Asset/fee distribution without consolidated positions: All assets and fees are directed to the protocol.
Alice and Bob create positions in epoch 1 but must wait until epoch 2 to consolidate their positions.
During epoch 2, they trigger a function to consolidate their positions. These positions are regarded as consolidated in epoch 3. Their stakes are added to a mapping(uint256 epoch => EpochStruct {uint256 totalStake, AssetReward{address token, uint256 amountDistributed}, uint256 distributedFees}).
When fees and assets are distributed, the corresponding AssetReward in the previous mapping is updated.
At the start of a new epoch, the current total stake is recorded.
If Alice or Bob wish to withdraw their rewards, they must iterate over every epoch in the mapping until the current epoch to access their rewards.
For position decrease, Alice and Bob need to withdraw their rewards.
To maintain updated consolidated positions, a mechanism can be introduced allowing users to pay gas in advance, rewarding keepers responsible for maintaining consolidated positions. This could serve as an additional revenue source for the protocol or could be enforced whenever a user increases their position.
This approach mitigates block gas limit DOS risks stemming from holders or pending stake arrays becoming excessively large.
Disclaimer: Due to contest time limitations, this solution remains intuitive and preliminary.
WARNING: In my professional opinion, this code should not be deployed until the mentioned bug regarding DOS of liquidation is resolved, as it compromises the entire protocol.
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.