Post
Share your knowledge.
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?
- Smart Contract
- Solidity
Answers
2Easy 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)
What network did you use?
Sepolia, and I fixed it by simply passing in the airnode address for the Nodary airnode rather than the ANU airnode address.
Do you know the answer?
Please log in and share it.
Solidity is an object-oriented, high-level language for implementing smart contracts. It is a curly-bracket language designed to target the Ethereum Virtual Machine (EVM).
- My ERC721 contract successfully deploys, but I can't verify the contract's source code with hardhat21
- Solidity and ethers.js Compute Different Addresses from the Same Signature21
- can't understand what are the locations(uint256)22
- How to reverse keccak256 in solidity22
- Clarification on Gas Refunds and Comparison Between "require" and "revert" in Smart Contracts21