Uniq Random Numbers - Without Chainlink

I am trying to assign unique tickets for users. The user can choose the number of tickets and get an allotment. The allocated tickets will be mapped to users.

``````pragma solidity ^0.8.11;
contract UniqTicket
{
// Initializing the state variable
uint public randNonce = 0;

uint256[] public allTickets;

function randMod(uint _modulus) public returns(uint){
randNonce++;
return uint(keccak256(abi.encodePacked(block.timestamp, msg.sender, randNonce, block.difficulty))) % _modulus;
}

function allotTickets(uint256 size) public{
for(uint i=0; i<size; i++) {
uint256 ticket = randMod(1000);
participants[msg.sender].push(ticket);
allTickets.push(ticket);
}
}

function getTickets(address _user) public view returns(uint256[] memory) {
return participants[_user];
}

function fetchAllTickets() public view returns(uint256[] memory) {
return allTickets;
}

}
``````

When users choose `allotTickets(200).` The user is getting duplicate numbers. Though randNonce is a unique counter.

Looking out for a solution, how to get unique numbers.

Sample Output:

``````[427,257,673,731,304,357,2,959,236,931,766,322,929,42,69,897,902,116,972,408,27,397,13,141,337,238,520,680,847,657,44,630,649,722,715,81,126,569,952,874,925,354,907,101,649,548,259,8,678,10,297,256,371,369,338,355,446,248,36,639,169,742,802,391,886,117,230,781,230,279,693,9,532,456,276,148,105,863,134,161,19,954,231,949,849,477,211,305,570,281,575,548,340,348,758,15,794,311,634,639,753,50,33,856,59,142,505,201,331,513,913,801,660,739,830,641,888,975,481,236,473,624,243,86,976,871,606,736,726,780,571,53,98,470,702,437,33,688,332,639,392,720,751,107,377,544,235,773,625,544,451,315,68,559,217,491,401,75,549,781,267,217,308,430,776,163,300,438,631,125,689,787,503,805,277,828,430,377,133,122,343,913,637,712,862,247,348,964,824,189,711,666,730,43,704,896,829,771,696,983]
``````

Thank you

To ensure unique ticket numbers, you can use a mapping to keep track of the allocated tickets. Please use this code below:

``````pragma solidity ^0.8.11;

contract UniqTicket {
// Initializing the state variable
uint public randNonce = 0;

mapping(uint256 => bool) public allocatedTickets;
uint256[] public allTickets;

function randMod(uint _modulus) public returns(uint){
randNonce++;
return uint(keccak256(abi.encodePacked(block.timestamp, msg.sender, randNonce, block.difficulty))) % _modulus;
}

function allotTickets(uint256 size) public {
for(uint i = 0; i < size; i++) {
uint256 ticket = randMod(1000);
while (allocatedTickets[ticket]) {
ticket = randMod(1000);
}
allocatedTickets[ticket] = true;
participants[msg.sender].push(ticket);
allTickets.push(ticket);
}
}

function getTickets(address _user) public view returns(uint256[] memory) {
return participants[_user];
}

function fetchAllTickets() public view returns(uint256[] memory) {
return allTickets;
}
}
``````

I added a new mapping called `allocated tickets` to keep track of the allocated ticket numbers. In the `allotTickets` function, added a `while` loop to generate a new random ticket number if the current ticket number is already allocated. This ensures that each ticket number is unique. Please note that this method may not be efficient for a large number of tickets, as the `while loop` may run for a long time if there are only a few unallocated tickets left. In such cases, you may want to consider alternative methods for generating unique ticket numbers.

• Ya checking back on mapping will solve the problem. What I am trying to understand is why by default it's not giving a unique random number. As i have passed timestamp, randnonce and block difficulty. Where as randNonce will be always unique Jun 11 at 7:21
• The random number generation method you're using is not guaranteed to produce unique numbers, even though you're using randNonce, block.timestamp, and block.difficulty as inputs. The reason is that the output of the keccak256 function is deterministic, meaning that it will always produce the same output for the same input. In your case, you're using the modulo operator (% _modulus) to limit the range of the random numbers. This operation can cause collisions, where different inputs produce the same output after applying the modulo operation. Jun 11 at 7:30
• As a result, even though randNonce is unique for each call, the output of the randMod function may not be unique. Jun 11 at 7:30
• @DEFIExpert: Can you ask your first comment as a separate question? Gourav spent time helping answer your original question, so please check it and accept it if it works. Gourav: moderators basically can only delete or not delete comments, and I think it would be more confusing to delete a comment at this stage. Thank you for helping the community!
– eth
Jun 11 at 20:02