Skip to main content

Ordered outcomes (default)

TL;DR

Use this algorithm to display the winners in ascending order.

This algorithm will randomly select winners among participants without preserving the order in which winners were drawn, they will be displayed in ascending order. For example, if the selected winners are 9,4,5,1 in that specific order, the algorithm will display 1,4,5,9, so it will look like the winner "9" was picked last, even though it was actually picked first.

The advantage is that it's a much faster algorithm compared to order-preserving algorithms, thus consuming less gas, and allowing more winners to be picked per draw.

Another advantage of displaying the winners in ascending order is that the list of winners is easier to read and you can quickly find out if a particular participant has won. This is especially useful when the number of winners is high.

This algorithm will be used by default if you don't specify an algorithm.

Solidity
function algorithmOrderedOutcomes(bytes totalEntropy, uint32 nbParticipants, uint32 nbWinners) private returns (uint32[] memory)
{
uint32[] memory winnerIndexes = new uint32[](nbWinners); // Fixed sized array, all elements initialize to 0
uint32 from = 0;

for (uint32 i = 0; i < nbWinners; i++) {

bytes8 extractedEntropy = extractBytes8(totalEntropy, from);
from += entropyNeededPerWinner;

// When i winners are already selected, we only need a random number between 0 and nbParticipants - i - 1 to select the next winner.
// ⚠️ Using 64-bit integers for the modulo operation is extremely important to prevent scaling bias ⚠️
// Then it is fine to convert the result to a 32-bit integer because we know that the output of the modulo will always be stricly less than nbParticipants which is a 32-bit integer
uint32 randomNumber = uint32(uint64(extractedEntropy) % uint64(nbParticipants - i));
uint32 nextWinner = randomNumber + 1; // We increment to convert the index to a line number
uint32 j = 0;

for (j = 0; j < i; j++) {
if (winnerIndexes[j] <= nextWinner) {
nextWinner++;
} else {
break;
}
}

for (uint32 k = i; k > j; k--) {
winnerIndexes[k] = winnerIndexes[k-1];
}

winnerIndexes[j] = nextWinner;
}

return winnerIndexes;
}