I can't get API3 QRNG to select a random enum value and mint an NFT based on this enum choice


I tried to make a contract that mints a token from an enum of options: RandomSurfaceReachT1.sol ``` // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.18; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol"; import "@api3/airnode-protocol/contracts/rrp/requesters/RrpRequesterV0.sol"; contract RandomSurfaceReachT1 is ERC721URIStorage, Ownable, RrpRequesterV0 { uint256 public tokenCounter; enum Classifier{FIRST, SECOND, THIRD} mapping(uint256 => Classifier) public tokenIdToClassifier; mapping(bytes32 => string) public requestIdToTokenURI; address public airnode; bytes32 public endpointId; address public sponsorWallet; mapping(bytes32 => bool) expectingRequestIdToBeFulfilled; mapping(bytes32 => address) requestToRequester; mapping(bytes32 => string) requestToName; event ReturnedSurfaceReachT1(bytes32 indexed requestId, uint256 randomNumber); constructor(address _airnodeRrp) RrpRequesterV0(_airnodeRrp) ERC721("SURFACE REACHT1 NFT", "SURFACE REACHT1 NFT"){ tokenCounter = 0; } function setRequestParameters( address _airnode, bytes32 _endpointId, address _sponsorWallet ) external onlyOwner { airnode = _airnode; endpointId = _endpointId; sponsorWallet = _sponsorWallet; } // QRNG Request Function function requestRandomSurfaceReachT1() public returns (bytes32) { bytes32 requestId = airnodeRrp.makeFullRequest( airnode, endpointId, address(this), sponsorWallet, address(this), this.mintSurfaceReacher.selector, "" ); expectingRequestIdToBeFulfilled[requestId] = true; requestToRequester[requestId] = msg.sender; return requestId; } // QRNG Fullfill Request function mintSurfaceReacher(bytes32 requestId, bytes calldata data) public { require( expectingRequestIdToBeFulfilled[requestId], "Request not awaiting fullfillment" ); expectingRequestIdToBeFulfilled[requestId] = false; uint256 newId = tokenCounter; uint256 randomNumber = abi.decode(data, (uint256)); string memory tokenURI = requestIdToTokenURI[requestId]; _safeMint(requestToRequester[requestId], newId); _setTokenURI(newId, tokenURI); Classifier classifier = Classifier(randomNumber % 3); tokenIdToClassifier[newId] = classifier; tokenCounter = tokenCounter + 1; emit ReturnedSurfaceReachT1(requestId, randomNumber); } function setTokenURI(uint256 tokenId, string memory _tokenURI) public { require( _isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved" ); _setTokenURI(tokenId, _tokenURI); } } ``` This code fails at every turn. I started with the code from this video https://youtu.be/MFgMpA819DU. I didn't want the strength or intelligence to be generated dynamically, I just had an array of 3 character types that I wanted chosen at random, from my contract: enum Classifier{FIRST, SECOND, THIRD}. I used this contract as a reference for how to select at random from an enum https://github.com/PatrickAlphaC/nft-mix/blob/main/contracts/AdvancedCollectible.sol. This Patrick Collins contract uses Chainlink but I swapped that out with API3. I deployed it with this script: ``` import { ethers } from "hardhat"; const hre = require("hardhat"); const dotenv = require("dotenv"); dotenv.config(); async function main() { const SurfaceReachT1NFT = await hre.ethers.getContractFactory("RandomSurfaceReachT1"); const surfaceReachT1NFT = await SurfaceReachT1NFT.deploy(process.env.AIRNODE_NODARY_ADDRESS); await surfaceReachT1NFT.deployed(); console.log("SurfaceReach1NFT deployed to:", surfaceReachT1NFT.address); } main() .then(() => process.exit(0)) .catch((error) => { console.error(error); process.exit(1); }); ``` I derived a sponsor wallet with this command: ``` npx @api3/airnode-admin derive-sponsor-wallet-address --airnode-xpub xpub6DXSDTZBd4aPVXnv6Q3SmnGUweFv6j24SK77W4qrSFuhGgi666awUiXakjXruUSCDQhhctVG7AQt67gMdaRAsDnDXv23bBRKsMWvRzo6kbf --airnode-address 0x9d3C147cA16DB954873A498e0af5852AB39139f2 --sponsor-address 0xed27fD189b37a1BFDD07F80b5292feC19b48f3AA ``` This command output my new sponsor wallet as "0x38f1ff4E68C6b01396B952100Af1fB363609A522" Notice that the sponsor-address is the same as my deployed contract address. I then setRequestParameters like this in hardhat console: ``` await contract.setRequestParameters(0x9d3C147cA16DB954873A498e0af5852AB39139f2, 0xfb6d017bb87991b7495f563db3c8cf59ff87b09781947bb1e417006ad7f55a78, 0x2ab9f26E18B64848cd349582ca3B55c2d06f507d) ``` Notice that "0x2ab9f26E18B64848cd349582ca3B55c2d06f507d" is Nodary's Sepolia address. I then funded my sponsor wallet (0x38f1ff4E68C6b01396B952100Af1fB363609A522) with Sepolia eth for gas fees but it still doesn't seem to work. What am I doing wrong?

Answers 2

What network did you use?

Easy fix, 0x6238772544f029ecaBfDED4300f13A3c4FE84E1D is the airnode address of Nodary which is the airnode I wanted to use for the qrng number. 0x9d3C147cA16DB954873A498e0af5852AB39139f2 is the address of the ANU airnode. So instread of `await contract.setRequestParameters(0x9d3C147cA16DB954873A498e0af5852AB39139f2, 0xfb6d017bb87991b7495f563db3c8cf59ff87b09781947bb1e417006ad7f55a78, 0x2ab9f26E18B64848cd349582ca3B55c2d06f507d)` I needed to do `await contract.setRequestParameters(0x6238772544f029ecaBfDED4300f13A3c4FE84E1D, 0xfb6d017bb87991b7495f563db3c8cf59ff87b09781947bb1e417006ad7f55a78, 0x2ab9f26E18B64848cd349582ca3B55c2d06f507d)`