Skip to content

Instantly share code, notes, and snippets.

@QingyangKong
Last active November 11, 2024 03:39
Show Gist options
  • Save QingyangKong/8605104cc04de60980c87f95c5e2a3b6 to your computer and use it in GitHub Desktop.
Save QingyangKong/8605104cc04de60980c87f95c5e2a3b6 to your computer and use it in GitHub Desktop.
// SPDX-License-Identifier: MIT
// Compatible with OpenZeppelin Contracts ^5.0.0
pragma solidity ^0.8.22;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/access/Ownable.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, ERC721Enumerable, ERC721URIStorage, VRFConsumerBaseV2Plus {
uint256 private _nextTokenId;
// chainlink vrf configuration, this is specific for Chainlink service in testnet Ethereum Sepolia
// please find configuration info for other testnets at https://docs.chain.link/vrf/v2-5/supported-networks
uint256 s_subscriptionId;
address vrfCoordinator = 0x9DdfaCa8183c41ad55329BdeeD9F6A8d53168B1B;
bytes32 s_keyHash = 0x787d74caea10b2b357790d5b5247c2f63d1d91572a9846f780606e4d953677ae;
uint32 callbackGasLimit = 100_000;
uint16 requestConfirmations = 3;
uint32 numWords = 1;
//metadata
string constant META_DATA_1 = "ipfs://QmXw7TEAJWKjKifvLE25Z9yjvowWk2NWY3WgnZPUto9XoA";
string constant META_DATA_2 = "ipfs://QmTFXZBmmnSANGRGhRVoahTTVPJyGaWum8D3YicJQmG97m";
string constant META_DATA_3 = "ipfs://QmSM5h4WseQWATNhFWeCbqCTAGJCZc11Sa1P5gaXk38ybT";
//record request -> tokenId
mapping(uint256 => uint256) requestIdToTokenId;
// please make sure you deploy the contract with EVM version Paris when deploy
constructor(uint256 subscriptionId) VRFConsumerBaseV2Plus(vrfCoordinator) ERC721("MyToken", "MTK"){
s_subscriptionId = subscriptionId;
}
function safeMint() public {
uint256 tokenId = _nextTokenId++;
_safeMint(msg.sender, tokenId);
uint256 requestId = s_vrfCoordinator.requestRandomWords(
VRFV2PlusClient.RandomWordsRequest({
keyHash: s_keyHash,
subId: s_subscriptionId,
requestConfirmations: requestConfirmations,
callbackGasLimit: callbackGasLimit,
numWords: numWords,
// Set nativePayment to true to pay for VRF requests with native token instead of LINK
extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: false}))
})
);
requestIdToTokenId[requestId] = tokenId;
}
function fulfillRandomWords(uint256 requestId, uint256[] calldata randomWords) internal override {
uint256 tokenId = requestIdToTokenId[requestId];
uint256 randomNumber = randomWords[0];
if(randomNumber % 3 == 0) {
_setTokenURI(tokenId, META_DATA_1);
} else if(randomNumber % 3 == 1) {
_setTokenURI(tokenId, META_DATA_2);
} else {
_setTokenURI(tokenId, META_DATA_3);
}
}
// The following functions are overrides required by Solidity.
function _update(address to, uint256 tokenId, address auth)
internal
override(ERC721, ERC721Enumerable)
returns (address)
{
return super._update(to, tokenId, auth);
}
function _increaseBalance(address account, uint128 value)
internal
override(ERC721, ERC721Enumerable)
{
super._increaseBalance(account, value);
}
function tokenURI(uint256 tokenId)
public
view
override(ERC721, ERC721URIStorage)
returns (string memory)
{
return super.tokenURI(tokenId);
}
function supportsInterface(bytes4 interfaceId)
public
view
override(ERC721, ERC721Enumerable, 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