ERC20Incentive contains two strategies, Raffles and Pools. This submission describes the weak random number generation used in drawRaffle() function when the strategy is set to Raffle.
The function is used to get an address from the entries mapping. The entries mapping contains addresses which have claimed a slot (purchased a ticket) for the raffle but since the function uses block.prevrandao and block.timestamp to generate PRNG, it can be exploited by malicious validators.
Here the function uses block.prevrandao and block.timestamp, both of these variables are added up, here how the struct looks in PRNG
struct PRNG {
uint256 state;
}
and then we get the winnerAddress by entries[_prng.next() % entries.length].
The next function does the following
assembly {
result := keccak256(prng, 0x20)
mstore(prng, result)
}
and then the length is used with the result to get the winner's address. The reason this is weak is because block.prevrandao and block.timestamp are known. Validators/Miners can influence this to a certain degree and get a desired outcome for themselves or someone else.
Impact
The winner of the raffle is not completely random. The current state of the function allows validators to influence the outcome
denzi_
High
Weak PRNG in
ERC20Incentive::drawRaffle()
Summary
ERC20Incentive contains two strategies, Raffles and Pools. This submission describes the weak random number generation used in
drawRaffle()
function when the strategy is set to Raffle.The function is used to get an address from the entries mapping. The entries mapping contains addresses which have claimed a slot (purchased a ticket) for the raffle but since the function uses
block.prevrandao and block.timestamp
to generate PRNG, it can be exploited by malicious validators.Vulnerability Detail
Here is the drawRaffle() function
Here the function uses
block.prevrandao and block.timestamp
, both of these variables are added up, here how the struct looks in PRNGand then we get the
winnerAddress
byentries[_prng.next() % entries.length]
.The next function does the following
and then the length is used with the result to get the winner's address. The reason this is weak is because block.prevrandao and block.timestamp are known. Validators/Miners can influence this to a certain degree and get a desired outcome for themselves or someone else.
Impact
The winner of the raffle is not completely random. The current state of the function allows validators to influence the outcome
Code Snippet
ERC20Incentive::drawRaffle()
Tool used
Manual Review
Recommendation
Implement chainlink vrf and use the answer to pick out an address.