A validator can manipulate the Chainlink request order to reroll the randomNumber
in his favor
#125
Labels
bug
Something isn't working
downgraded by judge
Judge downgraded the risk level of this issue
duplicate-445
edited-by-warden
grade-b
QA (Quality Assurance)
Assets are not at risk. State handling, function incorrect as to spec, issues with clarity, syntax
Lines of code
https://github.com/code-423n4/2023-03-wenwin/blob/main/src/RNSourceController.sol#L34
Vulnerability details
There is a
retry
function inRNSourceController
that is used to request anotherrandomNumber
to Chainlink, in case anything goes wrong with the first request called by theLottery
.This retry can be performed in an interval defined by
maxRequestDelay
.If a jackpot becomes big enough, a validator could be interested in manipulating the order request to effectively 'reroll the dice' in his favor, thus highly increasing his chance of winning the lottery.
Impact
A validator can manipulate the Chainlink request order to reroll the
randomNumber
in his favor, increasing his chance of winning the lottery.Proof of Concept
There is no lower limit for
maxRequestDelay
:The average block time on Polygon is 2, meaning a new block is produced every 2 seconds.
This means that this attack can be performed if the following is true:
maxRequestDelay < ~(2 seconds)
Let's suppose that a
Lottery
is initialized withmaxRequestDelay = 1 seconds
executeDraw
function is called, and Chainlink is invoked throughrequestRandomNumber
lastRequestFulfilled
isfalse
receiveRandomNumber
: let's call this pending transactiontransaction_A
retry
function after1 second
, and a newrequestRandomNumberFromSource
is madereceiveRandomNumber
again, let's call this pending transactiontransaction_B
transaction_B
beforetransaction_A
, because therandomNumber
generated is better for him in the former transactionLottery
finalizes the draw with therandomNumber
fromtransaction_B
, and nowdrawExecutionInProgress
isfalse
transaction_A
reverts with aDrawNotInProgress
errorTools Used
Manual review
Recommended Mitigation Steps
Put a lower limit for
maxRequestDelay
to avoid this type of attack, to be safe it should be some minutes.To compare, Ethereum mainnet currently takes an average of 12 seconds, while Bitcoin takes an average of 10 minutes per block.
The text was updated successfully, but these errors were encountered: