Skip to content

Instantly share code, notes, and snippets.

@QingyangKong
Created June 6, 2024 15:48
Show Gist options
  • Save QingyangKong/52b0a096b47d4263651a70d510ab1057 to your computer and use it in GitHub Desktop.
Save QingyangKong/52b0a096b47d4263651a70d510ab1057 to your computer and use it in GitHub Desktop.
// SPDX-License-Identifier: MIT
// Compatible with OpenZeppelin Contracts ^5.0.0
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import {AggregatorV3Interface} from "@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol";
import {VRFConsumerBaseV2Plus} from "@chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol";
import {VRFV2PlusClient} from "@chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol";
contract MyToken is ERC721, ERC721URIStorage, VRFConsumerBaseV2Plus {
uint256 private _nextTokenId;
// metadata for NFT
string constant METADATA_SHIBAINU = "ipfs://QmXw7TEAJWKjKifvLE25Z9yjvowWk2NWY3WgnZPUto9XoA";
string constant METADATA_HUSKY = "ipfs://QmTFXZBmmnSANGRGhRVoahTTVPJyGaWum8D3YicJQmG97m";
string constant METADATA_BULLDOG = "ipfs://QmSM5h4WseQWATNhFWeCbqCTAGJCZc11Sa1P5gaXk38ybT";
// minimum payment
uint256 constant MINIMUM_PAYMENT = 1 * 10 ** 18; // 1usd (wei)
// Data feed
AggregatorV3Interface dataFeed;
// vrf config
uint256 public s_subscriptionId;
bytes32 public keyHash =0x787d74caea10b2b357790d5b5247c2f63d1d91572a9846f780606e4d953677ae;
uint32 public callbackGasLimit = 500000;
uint16 public requestConfirmations = 3;
uint32 public numWords = 1;
//mapping for tokenId and reqId
mapping(uint256 => uint256) public reqIdToTokenId;
constructor(uint256 subId)
ERC721("MyToken", "MTK")
VRFConsumerBaseV2Plus(0x9DdfaCa8183c41ad55329BdeeD9F6A8d53168B1B)
{
// this is hardcoded for Sepolia
dataFeed = AggregatorV3Interface(0x694AA1769357215DE4FAC081bf1f309aDC325306);
s_subscriptionId = subId;
}
// make sure the minter pay minimum eth to mint a nft
function safeMint() public payable {
require(convertEthToUsd(msg.value) > MINIMUM_PAYMENT, "Please send more ETH"); // msg.valeu amount of eth, MIMI value of usd
uint256 tokenId = _nextTokenId++;
_safeMint(msg.sender, tokenId);
// send a vrf request
uint256 requestId;
requestId = s_vrfCoordinator.requestRandomWords(
VRFV2PlusClient.RandomWordsRequest({
keyHash: keyHash,
subId: s_subscriptionId,
requestConfirmations: requestConfirmations,
callbackGasLimit: callbackGasLimit,
numWords: numWords,
extraArgs: VRFV2PlusClient._argsToBytes(
VRFV2PlusClient.ExtraArgsV1({
nativePayment: false
})
)
})
);
reqIdToTokenId[requestId] = tokenId;
}
function fulfillRandomWords(
uint256 _requestId,
uint256[] calldata _randomWords
) internal override {
uint256 tokenId = reqIdToTokenId[_requestId];
uint256 randomNumber = _randomWords[0] % 3;
if(randomNumber == 0) {
//case 1
_setTokenURI(tokenId, METADATA_SHIBAINU);
} else if(randomNumber == 1) {
// case 2
_setTokenURI(tokenId, METADATA_HUSKY);
} else {
// case 3
_setTokenURI(tokenId, METADATA_BULLDOG);
}
}
function convertEthToUsd(uint256 ethAmount) public view returns (uint256) {
// value of ethAmount
return ethAmount * uint256(getChainlinkDataFeedLatestAnswer()) / 10 ** 8;
}
function getChainlinkDataFeedLatestAnswer() public view returns (int) {
// prettier-ignore
(
/* uint80 roundID */,
int answer,
/*uint startedAt*/,
/*uint timeStamp*/,
/*uint80 answeredInRound*/
) = dataFeed.latestRoundData();
return answer;
}
// The following functions are overrides required by Solidity.
function tokenURI(uint256 tokenId)
public
view
override(ERC721, ERC721URIStorage)
returns (string memory)
{
return super.tokenURI(tokenId);
}
function supportsInterface(bytes4 interfaceId)
public
view
override(ERC721, ERC721URIStorage)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment