Reputation: 1
I have been working on something that encapsulates chainlink random number on nfts to provide them to users, using a chainlink subscription and adding my smart contract as a comsumer. When working on testnet I am finding some times it gives me zero numbers and not a random one. This behaviour is random. Subscription is funded and smart contract added as a comsumer.
May this happen on mainnet also?
On most cases this kind of errors are only testnet timeouts, or other stuff related to slower infrastructure.
I wish to implement something to prevent shipping the NFT when zeroes are recevied:
I tried to put assert(randomNumber!=[zero]); but I got some errors, as gas stimation functions on wallets can ensure this, so they set highest fee.
Any suggestions to keep this secured?
This is the main testnet smart contract bsc address https://testnet.bscscan.com/address/0x74623BaE2c3AcC39Db224c236229dc4d5aD1F64d#code
is there any warranty the request random number operation finishes succesfully, or how can I take care of it on my code?
I have posted chainlink related functions too, where I slice the numbers to get them one by one in the lottery.
Subscription is funded and smart contract added as a comsumer. geting some times zero numbers and not a random one
these are the two functions
function closeSaleGetWinner()
external
nonReentrant
onlyRole(OPERATOR_ROLE)
{
requestRandomWords();
require(
isDrawLive,
"There's not a live draw neither ticket sale is opened"
);
uint256[6] memory numberOfMatches;
uint256 drawPrice;
// set the total pool price to BUSD smart contract balance
drawPrice =
checkBUSDContractBalance() *
allDraws[currentDraw].poolPercentage; // use 1 * 10**18 for use the whole pool
// close ticket sale and get random winner number from s_randomWords
isDrawLive = false;
//assert(s_randomWords[0]!=0);
allDraws[currentDraw].winnerNumber = s_slicedRandomWords;
//unchecked {
uint256 j;
Ticket storage _ticket;
uint256 _match;
// check and update matched numbers per ticket on allTickets structure
for (uint256 i = 0; i < drawToTickets[currentDraw].length; i++) {
j = drawToTickets[currentDraw][i];
_ticket = allTickets[j];
_match = checkWinner(_ticket);
_ticket.matchedNumbers = _match;
numberOfMatches[_match] = numberOfMatches[_match] + 1;
}
// after storing number of winners with [_match] matches calculate win per group
// it's time to overwrite reward variable with
// 1st the part of the price from the total pool for #i number of matches
// 2nd divide e
for (uint256 i = 0; i < 5; i++) {
allDraws[currentDraw].reward[i] =
allDraws[currentDraw].reward[i] *
drawPrice;
if (numberOfMatches[i + 1] > 0) {
allDraws[currentDraw].reward[i] = SafeMath.div(
allDraws[currentDraw].reward[i],
numberOfMatches[i + 1]
);
} else {
allDraws[currentDraw].reward[i] = 0;
}
}
// once stored delete random generated number for further checks
delete (s_randomWords);
delete (s_slicedRandomWords);
}
/*
compares the ticket number with the winner number of the draw and returns a value
representing matched number between 0 to 5 (6 values)
*/
function checkWinner(Ticket storage t) internal view returns (uint256) {
uint256 _match = 0;
// we go and compare digit by digit storing number of consecutive matches and stopping when
// there are no more coincidences
uint256[5] memory ticketNumber = t.number;
uint256[5] memory winnerNumber = allDraws[_drawIdCounter.current() - 1]
.winnerNumber;
for (uint256 i = 0; i < 5; i++) {
// If there exists any distinct
// lastTicketDigit, then return No
if (ticketNumber[i] == winnerNumber[i]) {
_match = _match + 1;
} else return _match;
}
return _match;
}
function buyRandomTicket() public nonReentrant {
uint256[] storage myTickets = accounts[msg.sender].myTicketsHistory;
require(isDrawLive, "Sorry there's no live draw by now");
require(!Address.isContract(msg.sender), "only EOA allowed");
address user = address(msg.sender);
uint256 _value = allDraws[currentDraw].ticketPrice;
// check balance and user allowance
uint256 busdUserBalance = BUSD.balanceOf(msg.sender);
require(busdUserBalance >= _value, "Not enough balance");
uint256 allowance = BUSD.allowance(msg.sender, address(this));
require(allowance >= _value, "Check the BUSD allowance");
uint256 devsReward = _value.mul(5).div(100);
uint256 otherReward = _value.mul(20).div(100);
// get payment
BUSD.safeTransferFrom(msg.sender, address(this), _value);
requestRandomWords();
BUSD.safeTransfer(w1, devsReward);
BUSD.safeTransfer(w2, devsReward);
BUSD.safeTransfer(w3, otherReward);
/*pay referral*/
if (accounts[msg.sender].referrer != address(0))
payReferral(_value, address(msg.sender));
Ticket memory randomTicket = Ticket(
user,
currentDraw,
_ticketIdCounter.current(),
s_slicedRandomWords,
false,
0
);
//require(s_randomWords[0]!=0);
uint256[] storage drawTickets = drawToTickets[currentDraw];
// add to the mapping to store tickets sold for a draw
drawTickets.push(randomTicket.ticketID);
myTickets.push(randomTicket.ticketID);
allTickets.push(randomTicket);
safeMint(user);
// set to 0 random storage variable for further checks
delete (s_randomWords);
delete (s_slicedRandomWords);
}
/* CHAINLINK FUNCTIONS */
// Assumes the subscription is funded sufficiently.
function requestRandomWords() internal {
// Will revert if subscription is not set and funded.
s_requestId = COORDINATOR.requestRandomWords(
keyHash,
s_subscriptionId,
requestConfirmations,
callbackGasLimit,
numWords
);
}
function fulfillRandomWords(
uint256, /* requestId */
uint256[] memory randomWords
) internal override {
uint256 _lastDigit;
s_randomWords = randomWords;
uint256 aux = randomWords[0];
for (uint256 i = 0; i < 5; i++) {
_lastDigit = aux % 10;
s_slicedRandomWords[i] = _lastDigit;
aux = aux / 10;
}
}
```
Upvotes: 0
Views: 160