Assessment reports>Yeet>Medium findings>Bias of the ,draftWinners, function in the Yeetback contract
Category: Business Logic

Bias of the draftWinners function in the Yeetback contract

Medium Severity
Medium Impact
Medium Likelihood

Description

For each round, the Yeetback contract randomly draws 10 winners (with replacement) whom the Yeetback pot for the round is evenly distributed to.

The following code is the draftWinners function, which samples 10 winners:

function draftWinners(uint256 randomNumber, uint256 round) private {
    uint256 potValue = potForRound[round];
    uint256 nrOfYeets = yeetsInRound[round].length;
    uint256 randomNumberCopy = randomNumber;
    uint16 nrOfWinners = 10;

    uint256 winnings = potValue / nrOfWinners;
    amountToWinners[round] = winnings;

    for (uint8 i; i < nrOfWinners; i++) {
        uint16 smallNumbers = uint16(randomNumberCopy & 0xFFFF);
        randomNumberCopy >>= 16;

        // Seed a new random number with some entropy from the large random number
        uint randomDataNumber = uint(keccak256(abi.encodePacked(smallNumbers, nrOfYeets)));
        uint winningYeetIndex = randomDataNumber % nrOfYeets; // index of the winning yeet
        address winnerAddress = yeetsInRound[round][winningYeetIndex];

        // Update amountToWinners and amountOfWins
        amountOfWins[round][winnerAddress] += 1;

        emit YeetbackWinner(round, winnerAddress, winnings);
    }
}

Each sampling is done by slicing two-byte data from the given random number, hashing the concatenation of the above two-byte slice and the number of Yeets in this round and calculating the hash number modulo the number of Yeets in this round.

In conclusion, 10 two-byte slices of the random number are respectively hashed with the number of Yeets to decide each winner of a sampling. This means that the contribution of randomness from the random number is only a two-byte size, which is insufficient for the law of large numbers to be applied.

Impact

The odds to win the Yeetback raffle is biased under the current algorithm. For instance, we have observed that, assuming there are 100 Yeets in the pot, the winning rate of the 63rd Yeet is 0.91% and the winning rate of the 87th Yeet is 1.10%.

An attacker can exploit this bias to unfairly maximize their expected return on the Yeetback contract.

Recommendations

Consider changing the winner-selection algorithm to remove the bias.

Remediation

This issue has been acknowledged by Sanguine Labs LTD, and a fix was implemented in commit edf75dfb.

Zellic © 2024Back to top ↑