Lottery
owner can manipulate the RNG to favour themselves, or other certain participants
#376
Labels
3 (High Risk)
Assets can be stolen/lost/compromised directly
bug
Something isn't working
duplicate-393
unsatisfactory
does not satisfy C4 submission criteria; not eligible for awards
Lines of code
https://github.com/code-423n4/2023-03-wenwin/blob/main/src/RNSourceController.sol#L46-L56
https://github.com/code-423n4/2023-03-wenwin/blob/main/src/RNSourceController.sol#L89-L104
Vulnerability details
The docs state that Chainlink VRF will be used as the source of randomness, whose subscription model is described here. A call is made to Chainlink's VRFCoordinatorV2
requestRandomWords
function, after which a response is sent back in the form of a call tofulfillRandomWords
on the requesting contract.A balance of LINK tokens is needed in order to pay for this request. If that balance is insufficient, then no response will be sent. This can be abused to manipulate the randomness of the lottery as follows: the owner of
Lottery
sets the subscriptions LINK balance to 0, waits for a sufficient amount of calls toretry
to be made such that they are able to callswapSource
, tops up their VRF subscription LINK balance and callsretry
once more, looks in the mempool for thefulfillRandomWords
function, and then frontruns it with a call toswapSource
if the random number result is unfavourable. This would indeed lead tofulfillRandomWords
reverting because once it attempts to executeonRandomNumberReceived
, the check will fail due tosource
being changed to a new address:Impact
The
Lottery
owner may manipulate the randomness of the draw, favouring themselves or disadvantaging other users. For example, this could be exploited in order to prevent users from winning the jackpot, therefore protecting the solvency of the protocol. A similar issue from a separate audit can be found here.Proof of Concept
Consider the following scenario:
Lottery
owner (perhaps using a different address) buys up lottery ticketsexecuteDraw
and each subsequent call toretry
all fail as there is insufficient LINK balance availableretry
, the Lottery owner tops up the LINK balancefulfillRandomWords
transaction and sees the random result-- they frontrun the transaction with a call to
swapSource
fulfillRandomWords
transaction reverts and the lottery does not settleretry
, they callswapSource
to change the source to the original Chainlink VRFCoordinatorV2 address and repeat the processTools Used
Manual review, Chainlink docs
Recommended Mitigation Steps
The only way to mitigate this vulnerability with the current protocol structure is to prevent the tampering of the subscription IDs LINK balance. This can be done by ensuring that the address responsible for managing the subscription is unable to withdraw LINK from the balance, by using the address of a simple smart contract which is only capable of adding funds to the subscription as the managing address.
An alternative approach would be to display the subscriptions LINK balance to the end user in some way to ensure the request will succeed, however this is insufficient since the owner can simply wait until the time of the draw (after many tickets will have been purchased) to reduce the LINK balance to 0.
The text was updated successfully, but these errors were encountered: