- Pause a token (stop all operations)
- Freeze a token for a specific account
- Wipe NFTs from a specific account
- Delete a token
Prerequisites
- ECDSA account from the Hedera Portal.
- Basic understanding of Solidity.
Table of Contents
- Step 1: Creating, minting, and transferring an NFT
- Step 2: Pause a Token
- Step 3: Unpause a Token
- Step 4: Freeze a Token for a Specific Account
- Step 5: Unfreeze a Token for a Specific Account
- Step 6: Wipe a Token
- Step 7: Delete a Token
- Step 8: Deploy Your HTS NFT Smart Contract
- Step 9: Minting an HTS NFT
- Step 10: Burning an HTS NFT
- Step 11: Run tests
- Conclusion
- Additional Resources
Step 1. Creating, minting, and burning an NFT
These steps of the flow have been covered in the Part 1 and Part 2. The only difference here is that we set a few different keys to handle pausing, freezing, and wiping. The previous tutorials covered creating NFT collection. Everything remains largely the same except for the following changes:- Add one additional line for managing the PAUSE key that can be used to prevent the token from being involved in any kind of operation.
- Add one additional line for managing the FREEZE key that can be used to freeze transfers of the specified token for the account.
- Add one additional line for managing the WIPE key that can be used to wipe the provided amount of fungible or non-fungible tokens from the specified Hedera account. This transaction does not delete tokens from the treasury account. Wiping an account’s tokens burns the tokens and decreases the total supply.
- Add one additional line for managing the DELETE key that can be used to mark a token as deleted, though it will remain in the ledger. Once deleted update, mint, burn, wipe, freeze, unfreeze, grant KYC, revoke KYC and token transfer transactions will resolve to TOKEN_WAS_DELETED. You cannot delete a specific NFT. You can delete the class of the NFT specified by the token ID after you have burned all associated NFTs associated with the token class
Key Code Snippet:
contracts/MyHTSTokenPFWD.sol
Step 2. Pause a Token
Let’s update our contract by:- Adding a new function
pauseTokento pause the token so it prevents the token from being involved in any kind of operation. - We will also define a new event
TokenPaused.
Key Code Snippet:
contracts/MyHTSTokenPFWD.sol
Step 3. Unpause a Token
Let’s update our contract by:- Adding a new function
unpauseTokento unpause the token so the token operations can be executed again. - We will also define a new event
TokenPaused.
Key Code Snippet:
contracts/MyHTSTokenPFWD.sol
Step 4. Freeze a Token for a Specific Account
Let’s update our contract by:- Adding a new function
freezeAccountto freezes a specific account, meaning it can neither send nor receive the token. Freezing is more granular than pausing; it only affects a specific account. This is useful for making soul-bound tokens. - We will also define a new event
AccountFrozen.
Key Code Snippet:
contracts/MyHTSTokenPFWD.sol
Step 5. Unfreeze a Token for a Specific Account
Let’s update our contract by:- Adding a new function
unfreezeAccountto unfreeze the token for a specific account. - We will also define a new event
AccountUnFrozen.
Key Code Snippet:
contracts/MyHTSTokenPFWD.sol
owner account can transact freely again.
Step 6. Wipe a Token
Let’s update our contract by:-
Adding a new function
wipeTokenFromAccountto wipe the NFT from an account. This effectively burns that token (i.e., reduces the total supply) from a non-treasury account. For fungible tokens, specify an amount to wipe; for non-fungible tokens (NFTs), we specify the serial numbers to be wiped. -
We will also define a new event
TokenWiped.
Key Code Snippet:
contracts/MyHTSTokenPFWD.sol
Step 7. Delete a Token
Let’s update our contract by:- Adding a new function
deleteTokento delete the token. This renders a token completely unusable for future operations. The token still exists on the ledger (you can query it), but all transactions (e.g., minting, transfers, etc.) will fail. The ADMIN key is required to delete. - We will also define a new event
TokenDeleted.
Key Code Snippet:
contracts/MyHTSTokenPFWD.sol
MyHTSTokenPFWD.sol:
contracts/MyHTSTokenPFWD.sol
Step 8: Deploy Your HTS NFT Smart Contract
Create a deployment script (deployPFWD.ts) in scripts directory:
scripts/deployPWD.ts
MyHTSTokenPFWD.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 9: Minting an HTS NFT
Create amintNFTPFWD.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/mintNFTPFWD.ts
How It Works
- Connects to Hedera testnet, gets the first signer, and attaches to your deployed MyHTSTokenPFWD contract.
- Reads the underlying HTS ERC721 facade address (tokenAddress) from the contract.
- Associates the signer via
token.associate()(EOA -> token contract) - Constructs <=100-byte UTF-8 metadata and calls mintNFT(recipient, metadata), then waits for the transaction receipt.
- Mints NFT to recipient
- 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 10: Burning an HTS NFT
Create a burn script (burnNFTPFWD.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/burnNFTPFWD.ts
How It Works
- Connects to Hedera testnet, gets the signer, attaches to MyHTSTokenPFWD, and reads the ERC721 facade tokenAddress.
- Checks token ownership and existing approval; if needed, approves the MyHTSTokenPFWD contract for the specific tokenId.
- Calls burnNFT(tokenId) on MyHTSTokenPFWD 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 11: Run tests(Optional)
You can find both types of tests in the Hedera-Code-Snippets repository. You will find the following files:contracts/MyHTSTokenPFWD.t.sol
- Ownership and access control: Verifies the constructor sets owner correctly and onlyOwner is enforced for create/pause/unpause/freeze/unfreeze/wipe/delete (non-owners revert with OwnableUnauthorizedAccount). * Pre-creation guards and validation: Ensures all HTS-dependent functions revert with “HTS: not created” before collection setup, and rejects minting when metadata exceeds 100 bytes. * Native HBAR flow: Confirms the contract can receive HBAR (HBARReceived event), blocks non-owner withdrawals, and allows the owner to withdraw all HBAR (HBARWithdrawn event) leaving balance at zero.
test/MyHTSTokenPFWD.ts
- End-to-end setup: Deploys the PFWD wrapper, creates the HTS NFT collection (with PAUSE/FREEZE/WIPE/ADMIN keys), retrieves the ERC721 facade address, generates/funds a second wallet, and associates both accounts on-chain via token.associate(). * Minting and event parsing: Mints NFT to deployer (tokenIdA) and to user2 (tokenIdB), parsing the NFTMinted event from wrapper logs; validates ownership/balances via the ERC721 facade. * Pause/unpause lifecycle: Asserts transfers revert while paused and succeed after unpausing, confirming correct enforcement of the PAUSE key. * Freeze/unfreeze enforcement: Freezes user2 to block outgoing transfers, then unfreezes and verifies transfers succeed again, demonstrating account-level restrictions. * Cleanup and failure handling: Attempts a wipe of user2’s token (freezing if necessary) and falls back to user-approved burn if wipe isn’t permitted; then approves and burns the remaining token, deletes the token (when supply is zero), and verifies subsequent mints fail.
Conclusion
In this guide, you saw how to replicate key HTS operations (pause, freeze, wipe, delete) directly in a Solidity contract by calling the HTS System Contract functions on Hedera. This approach provides fine-grained control via the contract’s ownership and key management, which is especially useful if you need all relevant HTS functionality in a single deployable smart contract. Key Takeaways:- If you want to perform the respective operations later, you must set the ADMIN, FREEZE, PAUSE, WIPE, and SUPPLY keys when creating a token via a contract.
- Any account that needs to receive or send the token must be associated with it.
- Pausing affects all operations globally while freezing targets a single account.
- Wiping NFTs effectively burns them, reducing total supply.
- Deleting a token makes it unusable for future operations but remains queryable on the ledger.