sherlock-audit / 2024-06-boost-aa-wallet-judging

3 stars 1 forks source link

denzi_ - Weak PRNG in `ERC20Incentive::drawRaffle()` #406

Open sherlock-admin3 opened 2 months ago

sherlock-admin3 commented 2 months ago

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

function drawRaffle() external override onlyOwner {
        if (strategy != Strategy.RAFFLE) revert BoostError.Unauthorized();

        LibPRNG.PRNG memory _prng = LibPRNG.PRNG({state: block.prevrandao + block.timestamp}); // @audit-issue weak prng

        address winnerAddress = entries[_prng.next() % entries.length];

        asset.safeTransfer(winnerAddress, reward);
        emit Claimed(winnerAddress, abi.encodePacked(asset, winnerAddress, reward));
    }

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

Code Snippet

ERC20Incentive::drawRaffle()

Tool used

Manual Review

Recommendation

Implement chainlink vrf and use the answer to pick out an address.