- Get all the performance, cost-efficiency, and security of native HTS tokens.
- Can embed custom, decentralized logic in your contract for advanced use cases.
- Create an NFT collection with a royalty fee schedule.
- Mint new NFTs with metadata pointing to IPFS.
- Burn an existing NFT.
You can take a look at the complete code in the Hedera-Code-Snippets
repository.
Prerequisites
- ECDSA account from the Hedera Portal.
- Basic understanding of Solidity.
Table of Contents
- Setup Project
- Step 1: Configure Hardhat
- Step 2: Creating an NFT collection via HTS(similar to ERC721)
- Step 3: Deploy HTS NFT Smart Contract
- Step 4: Minting an HTS NFT
- Step 5: Burning an HTS NFT
- Step 6: Run tests
- Conclusion
- Additional Resources
Setup Project
Set up your project by initializing the hardhat project.🚧 What's new: Hardhat 2 → 3
🚧 What's new: Hardhat 2 → 3
Key differences in Hardhat 3:
- compile → build
npx hardhat compileis nownpx hardhat build. This is the big one. The v3 migration guide explicitly shows using thebuildtask. - project init switch
v2 commonly usednpx hardhatornpx hardhat initto bootstrap. In v3 it’snpx hardhat --init.
- keystore helper commands are new
v3’s recommended flow includes a keystore plugin with commands likenpx hardhat keystore set HEDERA_RPC_URLandnpx hardhat keystore set HEDERA_PRIVATE_KEY. These weren’t standard in v2. - Foundry-compatiable Solidity tests
In addition to offering Javascript/Typescript integration tests, Hardhat v3 also integrates Foundry-compatible Solidity tests that allows developers to write unit tests directly in Solidity
- Enhanced Network Management
v3 allows tasks to create and manage multiple network connections simultaneously which is a significant improvement over the single, fixed connection available in version 2. This provides greater flexibility for scripts and tests that interact with multiple networks.
HEDERA_RPC_URL, we’ll have https://testnet.hashio.io/api
HEDERA_PRIVATE_KEY, enter the HEX Encoded Private Key for your ECDSA account from the Hedera Portal.
Install Dependencies
Next, install the required dependencies:github:hashgraph/hedera-smart-contracts . This also gets installed at @hashgraph/smart-contracts so we can easily call these contracts from our own contract.
Step 1: Configure Hardhat
Update yourhardhat.config.tsfile in the root directory of your project. This file contains the network settings so Hardhat knows how to interact with the Hedera Testnet.
hardhat.config.ts
ignition and we will be removing the default contracts that comes with hardhat default project so we will remove all the unnecessary directories and files first:
Step 2: Creating an NFT collection via HTS(similar to ERC721)
Create a new Solidity file (MyHTSToken.sol) in our contracts directory:
contracts/MyHTSToken.sol
How It Works
- Royalty fee: Sets a network-enforced 10% royalty with a 1 HBAR fallback (to initialOwner) via createNonFungibleTokenWithCustomFees.
- Token creation: Builds the HederaToken (name, symbol, treasury=this contract) and creates the NFT collection at deployment; tokenAddress is stored immutably.
- Keys and security: SUPPLY and ADMIN keys are set to the contractId, so mint/burn and any admin updates can only occur through this contract (not directly via SDK by EOAs).
- ERC721 facade: Dapps/wallets interact with the token like a standard ERC721 using IERC721(tokenAddress) for transfers/approvals; ownerOf and balanceOf are true view functions.
- Minting (safeMint): Only owner can mint; each mint creates a serial to the treasury, then transfers it to the recipient via ERC721 transferFrom. Recipient must be associated (or have auto-association) or the transfer will revert.
- Burning (ERC721Burnable-like): Owner or approved operator calls burn(tokenId). If not already in treasury, the contract (when approved) pulls the token from the owner, then burns it via HTS.
- HBAR handling: Contract can receive HBAR (receive/fallback) and the owner can withdraw any balance with withdrawHBAR().
- HTS nuances: NFT metadata is limited to 100 bytes per serial; token IDs are HTS serials (start at 1); association is required on Hedera for receiving NFTs.
Hedera Native Tokens(created via HTS) are highly interoperable with their
corresponding ERC Contracts. Hedera Accounts are able to transfer native NFTs
as though they are ERC-721 Smart Contracts!
Step 3: Deploy Your HTS NFT Smart Contract
Create a deployment script (deploy.ts) in scripts directory:
scripts/deploy.ts
MyHTSToken.deploy().
NoteFor most HTS System Smart Contract calls, an HBAR value is not required to be sent in the contract call; the gas fee will cover it. However, for expensive transactions, like Create HTS NFT Collection, the gas fee is reduced, and the transaction cost is covered by the payable amount. This is to reduce the gas consumed by the contract call.
Copy the deployed address—you’ll need this in subsequent steps.
Step 4: Minting an HTS NFT
Create amintNFT.ts script in your scripts directory to mint an NFT. Don’t forget to replace the <your-contract-address> with the address you’ve just copied.
scripts/mintNFT.ts
How It Works
- Connects to Hedera testnet, gets the first signer, and attaches to your deployed MyHTSToken contract.
- Reads the underlying HTS ERC721 facade address (tokenAddress) from the contract.
- Constructs <=100-byte UTF-8 metadata and calls mintNFT(recipient, metadata), then waits for the transaction receipt.
- Queries balanceOf(recipient) on the ERC721 facade and logs the current NFT count.
signer.address ). Then we verify the balance to see if we own an HTS NFT.
Mint an NFT:
Step 5: Burning an HTS NFT
Create a burn script (burnNFT.ts ) in your scripts directory. Make sure to replace <your-contract-address> to the MyHTSToken contract address you got from deploying and replace <your-token-id> with the tokenId you want to burn(eg. “1”) :
scripts/burnNFT.ts
How It Works
- Connects to Hedera testnet, gets the signer, attaches to MyHTSToken, and reads the ERC721 facade tokenAddress.
- Checks token ownership and existing approval; if needed, approves the MyHTSToken contract for the specific tokenId.
- Calls burnNFT(tokenId) on MyHTSToken and waits for the transaction receipt.
- Reads and logs the signer’s NFT balance from the ERC721 facade after the burn.
1, which is the HTS NFT you’ve just minted. To be sure the token has been deleted, let’s print the balance for our account to the terminal. The balance should show a balance of 0.
Burn the NFT:
Step 6: Run tests(Optional)
You can find both types of tests in the Hedera-Code-Snippets repository. You will find the following files:contracts/MyHTSToken.t.sol
- Ownership and access control: Ensures constructor sets the correct owner and that onlyOwner is enforced for createNFTCollection (non-owners revert with OwnableUnauthorizedAccount). * Pre-creation guards: Confirms HTS-dependent functions (mint, burn) revert with “HTS: not created” before the collection is created. * HBAR handling: Verifies the contract can receive HBAR (HBARReceived event), blocks non-owner withdrawals, and lets the owner withdraw all HBAR (HBARWithdrawn event) leaving the contract balance at zero.
test/MyHTSToken.ts
- Deployment and setup: Deploys the wrapper, creates the HTS NFT collection (funded with 15 HBAR), and retrieves/validates the ERC721 facade address.
- Mint with metadata: Mints an NFT to the deployer with metadata (<= 100 bytes), asserts the NFTMinted event, and extracts the tokenId from wrapper logs.
- ERC721 interactions: Uses a minimal ERC721 ABI to query owner/balance and manage approvals without relying on full artifacts.
- Burn flow: Ensures the wrapper is approved for the specific tokenId (approves if needed), then burns via the wrapper and asserts the NFTBurned event.
- Post-burn check: Reads the deployer’s ERC721 balance after burn to confirm calls succeed (balance may vary if multiple NFTs exist).
Conclusion
Using Solidity on Hedera, you can create, mint and burn native NFTs with minimal code thanks to the HTS System Contract. In this tutorial, you saw how to:- Create a new NFT class with royalty fees (
createNFTCollection). - Mint new tokens (
mintNFT). - Burn tokens when they are no longer needed (
burnNFT).