This repository has been archived by the owner on Oct 1, 2023. It is now read-only.
nobody2018 - Malicious user can make rolloverQueue never get processed #172
Labels
Has Duplicates
A valid issue with 1+ other issues describing the same vulnerability
Medium
A valid Medium severity issue
Reward
A payout will be made for this issue
Won't Fix
The sponsor confirmed this issue will not be fixed
nobody2018
medium
Malicious user can make rolloverQueue never get processed
Summary
rolloverQueue
is shared by all epochs. For each round of epoch,mintRollovers
will processrolloverQueue
from the beginning. A normal user callsenlistInRollover
to enter the rolloverQueue, and in the next round of epoch, he will calldelistInRollover
to exit the rolloverQueue. In this case,rolloverQueue.length
is acceptable. However, malicious user can make therolloverQueue.length
huge, causing the relayer to consume a huge amount of gas for every round of epoch. Carousel will send relayerFee to relayer in order to encourage external relayer to callmintRollovers
. Malicious user can make external relayer unwilling to callmintRollovers
. Ultimately, rolloverQueue will never be processed.Vulnerability Detail
Let's assume the following scenario:
relayerFee is 1e18. The current epochId is E1, and the next epochId is E2. At present,
rolloverQueue
has 10 normal userQueueItem
. Bob has deposited 1000e18 assets before the start of E1, sobalanceOf(bob, E1) = 1000e18
.Bob creates 1000 addresses, each address has
setApprovalForAll
to bob. He calls two functions for each address:Carousel.safeTransferFrom(bob, eachAddress, E1, 1e18)
Carousel.enlistInRollover(E1, 1e18, eachAddress)
, 1e18 equal to minRequiredDeposit.rolloverQueue.length
equals to 1010(1000+10).These 1000 addresses will never call
delistInRollover
to exit the rolloverQueue, so no matter whether these addresses win or lose, their QueueItem will always be in the rolloverQueue. In each round of epoch, the relayer has to process at least 1000 QueueItems, and these QueueItems are useless. Malicious users only need to do it once to cause permanent affects.When a normal user loses in a certain round of epoch, he may not call delistInRollover to exit the rolloverQueue. For example, he left the platform and stopped playing. In this case, rolloverQueue.length will become larger and larger as time goes by.
Carousel contract will not send any relayerFee to the relayer, because these useless QueueItem will not increase the value of [executions](https://github.com/sherlock-audit/2023-03-Y2K/blob/main/Earthquake/src/v2/Carousel/Carousel.sol#L447). Obviously, calling
mintRollovers
has no benefit for the relayer. Therefore, no relayer is willing to do this.Impact
The relayer consumes a huge amount of gas for calling
mintRollovers
for each round of epoch. In other words, as long as the rolloverQueue is unacceptably long, it is a permanent DOS.Code Snippet
https://github.com/sherlock-audit/2023-03-Y2K/blob/main/Earthquake/src/v2/Carousel/Carousel.sol#L361-L459
https://github.com/sherlock-audit/2023-03-Y2K/blob/main/Earthquake/src/v2/Carousel/Carousel.sol#L238-L271
Tool used
Manual Review
Recommendation
We should change the single queue to queue mapping. In this way, relayer only needs to process the queue corresponding to the epochId.
The text was updated successfully, but these errors were encountered: