Solidity.

帖子

分享您的知识。

Christian O'Connor.
Apr 08, 2023
专家问答

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
0
2
分享
评论
.

答案

2
Christian O'Connor.
Apr 9 2023, 08:31

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)

0
最佳答案
评论
.
Freitag.
Apr 10 2023, 01:00

What network did you use?

0
评论
.
Christian O'Connor.
Apr 10 2023, 01:21

Sepolia, and I fixed it by simply passing in the airnode address for the Nodary airnode rather than the ANU airnode address.

你知道答案吗?

请登录并分享。

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).

38帖子47答案
Sui.X.Peera.

赚取你的 1000 Sui 份额

获取声誉积分,并因帮助 Sui 社区成长而获得奖励。

我们使用 cookie 确保您在我们的网站上获得最佳体验。
更多信息