Hard one - Not using this one
Easy One
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.11;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Base64.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
string constant SVG_START = '<svg xmlns="<http://www.w3.org/2000/svg>" width="500" height="500" fill="none" font-family="sans-serif"><defs><filter id="A" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse" height="500" width="500"><feDropShadow dx="1" dy="2" stdDeviation="8" flood-opacity=".67" width="200%" height="200%" /></filter><linearGradient id="B" x1="0" y1="0" x2="15000" y2="0" gradientUnits="userSpaceOnUse"><stop offset=".05" stop-color="#ad00ff" /><stop offset=".23" stop-color="#4e00ec" /><stop offset=".41" stop-color="#ff00f5" /><stop offset=".59" stop-color="#e0e0e0" /><stop offset=".77" stop-color="#ffd810" /><stop offset=".95" stop-color="#ad00ff" /></linearGradient><linearGradient id="C" x1="0" y1="60" x2="0" y2="110" gradientUnits="userSpaceOnUse"><stop stop-color="#d040b8" /><stop offset="1" stop-color="#e0e0e0" /></linearGradient></defs><path fill="url(#B)" d="M0 0h15000v500H0z"><animateTransform attributeName="transform" attributeType="XML" type="translate" from="0 0" to="-14500 0" dur="16s" repeatCount="indefinite" /></path><circle fill="#1d1e20" cx="100" cy="90" r="45" filter="url(#A)" /><text x="101" y="99" text-anchor="middle" class="nftLogo" font-size="32px" fill="url(#C)" filter="url(#A)">D_D<animateTransform attributeName="transform" attributeType="XML" type="rotate" from="0 100 90" to="360 100 90" dur="5s" repeatCount="indefinite" /></text><g font-size="32" fill="#fff" filter="url(#A)"><text x="250" y="280" text-anchor="middle" class="tierName">';
string constant SVG_END = "</text></g></svg>";
string constant TIER_NAME_0 = "Basic";
string constant TIER_NAME_1 = "Medium;
string constant TIER_NAME_2 = "Premium";
uint256 constant TIER_VALUE_0 = 0.01 ether;
uint256 constant TIER_VALUE_1 = 0.02 ether;
uint256 constant TIER_VALUE_2 = 0.05 ether;
contract TierNFT is ERC721, Ownable {
uint256 public totalSupply;
mapping(uint256 => uint256) public tokenTier;
constructor(string memory _name, string memory _symbol)
ERC721(_name, _symbol)
{}
function mint() public payable {
require(
msg.value >= TIER_VALUE_0,
"Not enough value for the minimum Tier"
);
uint256 tierId = 0;
if (msg.value >= TIER_VALUE_2) tierId = 2;
else if (msg.value >= TIER_VALUE_1) tierId = 1;
totalSupply++;
_safeMint(msg.sender, totalSupply);
tokenTier[totalSupply] = tierId;
}
// Create the tokenURI json on the fly without creating files individually
function tokenURI(uint256 tokenId)
public
view
virtual
override
returns (string memory)
{
require(_exists(tokenId), "Nonexistent token");
string memory tierName = tokenTier[tokenId] == 2
? TIER_NAME_2
: tokenTier[tokenId] == 1
? TIER_NAME_1
: TIER_NAME_0;
string memory imageSVG = string(
abi.encodePacked(SVG_START, tierName, SVG_END)
);
string memory json = Base64.encode(
bytes(
string(
abi.encodePacked(
'{"name": "',
name(),
" #",
Strings.toString(tokenId),
'", "description": "TierNFTs collection", "image": "data:image/svg+xml;base64,',
Base64.encode(bytes(imageSVG)),
'","attributes":[{"trait_type": "Tier", "value": "',
tierName,
'" }]}'
)
)
)
);
return string(abi.encodePacked("data:application/json;base64,", json));
}
// Function to withdraw funds from contract
function withdraw() public onlyOwner {
// Check that we have funds to withdraw
uint256 balance = address(this).balance;
require(balance > 0, "Balance should be > 0");
// Withdraw funds.
(bool success, ) = payable(owner()).call{value: balance}("");
require(success, "Withdraw failed");
}
}
Deploy Script
const hre = require("hardhat");
/** Set contract and collection name **/
const CONTRACT_NAME = "TierNFT"
const COLLECTION_NAME = "TierNFT"
const COLLECTION_SYMBOL = "Tier"
/** Main deploy function **/
async function main() {
const contractFactory = await hre.ethers.getContractFactory(CONTRACT_NAME);
const contract = await contractFactory.deploy(COLLECTION_NAME, COLLECTION_SYMBOL);
await contract.deployed();
// Print our newly deployed contract address
console.log(`Contract deployed to ${contract.address}`);
}
/** Run Main function - Do not change **/
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
Install dotenv
npm install dotenv --save
.env
file
PRIVATE_KEY=f8abc629b....
hardhat.config.js
Config
require("@nomicfoundation/hardhat-toolbox");
require('dotenv').config();
/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {
solidity: "0.8.11",
networks: {
mumbai: {
url: "<https://rpc-mumbai.maticvigil.com>",
accounts: [process.env.PRIVATE_KEY]
}
},
};
Deploy command
npx hardhat run scripts/deploy.js --network mumbai
mint.js
script (copy the contract's address)
const hre = require("hardhat");
/** Set contract and collection name **/
const CONTRACT_NAME = "TierNFT"
const CONTRACT_ADDRESS = "0x...."
const VALUE_TIER_0 = "0.01" // in ethers/matic
const VALUE_TIER_1 = "0.02" // in ethers/matic
const VALUE_TIER_2 = "0.05" // in ethers/matic
/** Main deploy function **/
async function main() {
const contractFactory = await hre.ethers.getContractFactory(CONTRACT_NAME)
const contract = await contractFactory.attach(CONTRACT_ADDRESS)
// Print our newly deployed contract address
console.log(`Attached contract: ${contract.address}`)
// Call the mint function for Tier 0
let txn = await contract.mint({ value: hre.ethers.utils.parseEther(VALUE_TIER_0) })
await txn.wait() // Wait for the NFT to be minted
console.log("Minted a Tier 0 NFT!")
// Call the mint function for Tier 1
txn = await contract.mint({ value: hre.ethers.utils.parseEther(VALUE_TIER_1) })
await txn.wait() // Wait for the NFT to be minted
console.log("Minted a Tier 1 NFT!")
// Call the mint function for Tier 2
txn = await contract.mint({ value: hre.ethers.utils.parseEther(VALUE_TIER_2) })
await txn.wait() // Wait for the NFT to be minted
console.log("Minted a Tier 2 NFT!")
let totalSupply = await contract.totalSupply()
console.log("Collection's new totalSupply: ", totalSupply)
}
/** Run Main function - Do not change **/
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
Mint command