Problem with fullfilRandomWords() when using Chainlink’s VRFConsumerBaseV2, Subscription method

huangapple go评论45阅读模式
英文:

Problem with fullfilRandomWords() when using Chainlink's VRFConsumerBaseV2 , Subscription method

问题

以下是您要翻译的部分:

  • My fulfillRewards function isn't either receiving the randomWords from vrf or there's a problem with filtering them, since my getAddressWithMostMints works so it is able to check the nftContract functions
  • This is my current Raffle code that uses Chainlink VRF (Verifiable Random Function) to select random winners from a collection of NFTs. The contract is built using Solidity and inherits from VRFConsumerBaseV2 and ConfirmedOwner. Here's an overview of its main features:
  • Interacts with an external NFT contract using the INFTContract interface, allowing it to query the owner of a token and the total supply of the NFTs.
  • Stores information about the request made to the Chainlink VRF Coordinator in the RequestStatus struct and maintains a mapping of request IDs to their corresponding status.
  • Allows the contract owner to make a request to the Chainlink VRF Coordinator to generate random numbers.
  • Determines the address with the most mints using the getAddressWithMostMints function.
  • The getRandomWinner function, callable only by the contract owner, selects random winners for the raffle in the following steps:
    a. The function first calls the requestRandomWords function, which sends a request to the Chainlink VRF Coordinator to generate random numbers.
    b. The actual random words generated by the Chainlink VRF Coordinator are processed in the fulfillRandomWords() function, which is called by the VRF Coordinator after the random numbers are generated. This function checks for duplicates and adds the selected winners to the winners array.
    c. The address with the most mints is determined by calling getAddressWithMostMints and added to the list of winners.
    d. The raffle is marked as ended by setting the raffleEnded flag to true.
  • Allows users to check the status of a Chainlink VRF request by calling the getRequestStatus() function, which returns the fulfillment status and the random words generated for a given request ID.
英文:

My fulfillRewards function isn't either receiving the randomWords from vrf or there's a problem with filtering them, since my getAddressWithMostMints works so it is able to check the nftContract functions

This is my current Raffle code that uses Chainlink VRF (Verifiable Random Function) to select random winners from a collection of NFTs. The contract is built using Solidity and inherits from VRFConsumerBaseV2 and ConfirmedOwner. Here's an overview of its main features:

Interacts with an external NFT contract using the INFTContract interface, allowing it to query the owner of a token and the total supply of the NFTs.

Stores information about the request made to the Chainlink VRF Coordinator in the RequestStatus struct and maintains a mapping of request IDs to their corresponding status.

Allows the contract owner to make a request to the Chainlink VRF Coordinator to generate random numbers.

Determines the address with the most mints using the getAddressWithMostMints function.

The getRandomWinner function, callable only by the contract owner, selects random winners for the raffle in the following steps:
a. The function first calls the requestRandomWords function, which sends a request to the Chainlink VRF Coordinator to generate random numbers.
b. The actual random words generated by the Chainlink VRF Coordinator are processed in the fulfillRandomWords() function, which is called by the VRF Coordinator after the random numbers are generated. This function checks for duplicates and adds the selected winners to the winners array.
c. The address with the most mints is determined by calling getAddressWithMostMints and added to the list of winners.
d. The raffle is marked as ended by setting the raffleEnded flag to true.

Allows users to check the status of a Chainlink VRF request by calling the getRequestStatus() function, which returns the fulfillment status and the random words generated for a given request ID.

`\`// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol";
import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol";
import "@chainlink/contracts/src/v0.8/ConfirmedOwner.sol";
// Interface for the NFT contract
interface INFTContract {
function totalSupply() external view returns (uint256);
function ownerOf(uint256 tokenId) external view returns (address);
function balanceOf(address owner) external view returns (uint256);
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);
}
contract Raffle is VRFConsumerBaseV2, ConfirmedOwner {
// Struct to store the status of a request made to the VRFCoordinator contract
struct RequestStatus {
bool fulfilled; // whether the request has been successfully fulfilled
bool exists; // whether a requestId exists
uint256[] randomWords; // the random words generated for the request
}
// Struct to store the address of an owner and the number of NFT tokens they own
struct AddressMintCount {
address addr;
uint256 count;
}
// Mapping of requestId to RequestStatus
mapping(uint256 => RequestStatus) public s_requests;
// VRFCoordinator contract instance
VRFCoordinatorV2Interface COORDINATOR;
// Subscription ID for making requests to the VRFCoordinator contract
uint64 s_subscriptionId;
// Array of past request IDs
uint256[] public requestIds;
// ID of the last request made
uint256 public lastRequestId;
// Key hash for generating random numbers
bytes32 immutable keyHash;
// Address of the Link token contract
address public immutable linkToken;
// NFT contract instance
INFTContract public nftContract;
// Minimum and maximum NFT token IDs for the raffle
uint256 public minMints;
uint256 public maxMints;
// Flag indicating whether the raffle has ended or not
bool public raffleEnded;
// Array of winner addresses
address[] public winners;
// Fee required to make a request to the VRFCoordinator contract
uint256 internal fee;
// Gas limit for the callback function to process a request
uint32 callbackGasLimit = 100000;
// Number of confirmations required for a request to be processed
uint16 requestConfirmations = 3;
// Number of random words to be generated in a request
uint32 numWords = 2;
// Address of the VRF Coordinator contract used to generate random numbers
address vrfCoordinator = 0xbd13f08b8352A3635218ab9418E340c60d6Eb418;
// Address of the Link token contract
address linkAddress = 0xfaFedb041c0DD4fA2Dc0d87a6B0979Ee6FA7af5F;
// Address of the VRFWrapper contract used to interface with the VRF Coordinator contract
address wrapperAddress = 0x38336BDaE79747a1d2c4e6C67BBF382244287ca6;
// Event emitted when a request to the VRFCoordinator contract is sent
event RequestSent(uint256 requestId, uint32 numWords);
// Event emitted when a request to the VRFCoordinator contract is fulfilled
event RequestFulfilled(uint256 requestId, uint256[] randomWords);
constructor(
uint64 subscriptionId, 
address _nftContractAddress
)
VRFConsumerBaseV2(vrfCoordinator)
ConfirmedOwner(msg.sender)
{
COORDINATOR = VRFCoordinatorV2Interface(vrfCoordinator);
s_subscriptionId = subscriptionId;
keyHash = 0x121a143066e0f2f08b620784af77cccb35c6242460b4a8ee251b4b416abaebd4;
linkToken = linkAddress;
nftContract = INFTContract(_nftContractAddress);
// Hardcode minMints and maxMints
minMints = 1;
maxMints = 30;
raffleEnded = false;
}
// Function to check if the raffle is ready to be executed
function isRaffleReady() public view returns (bool) {
return nftContract.totalSupply() >= maxMints;
}
// Function to display all the winners
function printWinners() public view returns (address[] memory){
return winners;
}
// Function to select a random winner using Chainlink VRF
function getRandomWinner() public onlyOwner returns (address[] memory) {
uint256 requestId = requestRandomWords();
address winner = getAddressWithMostMints();
winners.push(winner);
raffleEnded=true;
return winners;
}
// Function to make a request to the VRFCoordinator contract to generate random words
function requestRandomWords() public onlyOwner returns (uint256 requestId) {
requestId = COORDINATOR.requestRandomWords(
keyHash,
s_subscriptionId,
requestConfirmations,
callbackGasLimit,
numWords
);
s_requests[requestId] = RequestStatus({
randomWords: new uint256[](0),
exists: true,
fulfilled: false
});
requestIds.push(requestId);
lastRequestId = requestId;
emit RequestSent(requestId, numWords);
return requestId;
}
function fulfillRandomWords(
uint256 \_requestId,
uint256\[\] memory \_randomWords
) internal override {
require(s_requests\[\_requestId\].exists, "request not found");
require(!s_requests\[\_requestId\].fulfilled, "request already fulfilled");
s_requests[_requestId].fulfilled = true;
s_requests[_requestId].randomWords = _randomWords;
for (uint256 i = 0; i < _randomWords.length; i++) {
uint256 result = (_randomWords[i] % maxMints) + minMints;
address winner = nftContract.ownerOf(result);
while (isWinnerDuplicate(winner)) {
result = (_randomWords[i] % maxMints) + minMints;
winner = nftContract.ownerOf(result);
}
winners.push(winner);
}
emit RequestFulfilled(_requestId, _randomWords);
}
// Function to check if a winner has already been selected
function isWinnerDuplicate(address winner) private view returns (bool) {
for (uint256 i = 0; i < winners.length; i++) {
if (winners[i] == winner) {
return true;
}
}
return false;
}
// Function to determine the address with the most mints
function getAddressWithMostMints() public view returns (address) {
address addrWithMostMints = address(0);
uint256 mostMints = 0;
uint256 addrMintCountIndex = 0;
AddressMintCount[200] memory addrMintCounts;
for (uint256 tokenId = minMints; tokenId <= maxMints; tokenId++) {
address currentOwner = nftContract.ownerOf(tokenId);
bool found = false;
for (uint256 i = 0; i < addrMintCountIndex; i++) {
if (addrMintCounts[i].addr == currentOwner) {
addrMintCounts[i].count++;
found = true;
break;
}
}
if (!found) {
AddressMintCount memory newAddressMintCount = AddressMintCount({
addr: currentOwner,
count: 1
});
addrMintCounts[addrMintCountIndex] = newAddressMintCount;
addrMintCountIndex++;
}
}
for (uint256 i = 0; i < addrMintCountIndex; i++) {
if (addrMintCounts[i].count > mostMints) {
addrWithMostMints = addrMintCounts[i].addr;
mostMints = addrMintCounts[i].count;
}
}
return addrWithMostMints;
}
// Function to check the status of a Chainlink VRF request
function getRequestStatus(uint256 _requestId) external view returns (bool fulfilled, uint256[] memory randomWords) {
require(s_requests[_requestId].exists, "request not found");
RequestStatus memory request = s_requests[_requestId];
return (request.fulfilled, request.randomWords);
}
}``

答案1

得分: 0

确保您拥有要请求随机单词的链的正确数值。建议为所有变量(callbackGasLimit、requestConfirmations、numWords、vrfCoordinator、linkAddress、keyHash)创建设置方法,以防万一。

英文:

Make sure you have the right values for the Chain you are trying to ask for random Words. I'd create set methods for all variables (callbackGasLimit, requestConfirmations, numWords, vrfCoordinator, linkAddress, keyHash) just in case.

huangapple
  • 本文由 发表于 2023年3月31日 18:55:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/75897736.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定