mcpField
H
HTS System Contract Skill

HTS System Contract Skill

github.com/hedera-devDevelopment2891 installsUpdated 8w ago
Repository

About HTS System Contract Skill

HTS System Contract Skill is a reference skill for developers using Hedera Token Service from Solidity contracts. It covers token operations, compliance controls, fees, response handling, and common implementation patterns.

Key features

  1. 01HTS precompile usage at `0x167`
  2. 02Fungible token and NFT patterns
  3. 03Token key construction guidance
  4. 04KYC, freeze, and pause controls
  5. 05Custom fee references
  6. 06Response-code and error guidance

Use cases

  1. 01Creating Hedera-native tokens in Solidity
  2. 02Adding compliance controls to token contracts
  3. 03Handling token fees and response codes

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/hedera-dev/hedera-skills --skill hts-system-contract-skill

After installing, type/hts-system-contract-skillin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

references/
response-codes.md
compliance.md
api.md
keys.md
fees.md
troubleshooting.md
structs.md

Details

From the project README

Hedera Token Service (HTS) System Contract

HTS precompile at 0x167 enables Solidity contracts to create and manage Hedera-native tokens with built-in compliance controls (KYC, freeze, pause) and custom fees.

Quick Reference

Imports:

import {HederaTokenService} from "@hashgraph/smart-contracts/contracts/system-contracts/hedera-token-service/HederaTokenService.sol";
import {KeyHelper} from "@hashgraph/smart-contracts/contracts/system-contracts/hedera-token-service/KeyHelper.sol";
import {ExpiryHelper} from "@hashgraph/smart-contracts/contracts/system-contracts/hedera-token-service/ExpiryHelper.sol";
import {HederaResponseCodes} from "@hashgraph/smart-contracts/contracts/system-contracts/hedera-token-service/HederaResponseCodes.sol";

Safe variants (auto-revert on failure): SafeHTS.sol, SafeViewHTS.sol

Critical: HBAR Payment Required

Token creation requires explicit HBAR value payment (not just gas):

// ❌ WRONG - fails with INSUFFICIENT_TX_FEE
(int rc, address token) = createNonFungibleToken(token);

// ✅ CORRECT
(int rc, address token) = createNonFungibleToken{value: msg.value}(token);

Call from TypeScript:

await contract.createToken(name, symbol, {
  gasLimit: 350_000,
  value: ethers.parseEther("15"), // ~$1-2 USD of HBAR
});

Token Key System

Seven key types control token operations (bit positions for keyType field):

KeyBitValueControls
ADMIN01Update token, keys, deletion
KYC12Grant/revoke KYC
FREEZE24Freeze/unfreeze accounts
WIPE38Wipe balances
SUPPLY416Mint/burn
FEE532Update fees
PAUSE664Pause all operations

Use KeyHelper for key construction:

keys[0] = getSingleKey(KeyType.SUPPLY, KeyValueType.CONTRACT_ID, address(this));

See references/keys.md for key value types and JSON tuple format.

Association Model

Accounts must associate with tokens before receiving them:

int rc = associateToken(accountAddress, tokenAddress);
require(
    rc == HederaResponseCodes.SUCCESS ||
    rc == HederaResponseCodes.TOKEN_ALREADY_ASSOCIATED_TO_ACCOUNT,
    "Association failed"
);

Common Patterns

Fungible Token Creation
function createToken() external payable {
    IHederaTokenService.HederaToken memory token;
    token.name = "My Token";
    token.symbol = "MTK";
    token.treasury = address(this);
    token.expiry = createAutoRenewExpiry(address(this), 7776000); // 90 days

    (int rc, address created) = createFungibleToken{value: msg.value}(
        token, 1000000, 18  // initialSupply, decimals
    );
    require(rc == HederaResponseCodes.SUCCESS, "Create failed");
}
Mintable NFT Collection
function createNFT() external payable {
    IHederaTokenService.HederaToken memory token;
    token.name = "My NFT";
    token.symbol = "MNFT";
    token.treasury = address(this);
    token.tokenSupplyType = true;  // FINITE
    token.maxSupply = 10000;

    IHederaTokenService.TokenKey[] memory keys = new IHederaTokenService.TokenKey[](1);
    keys[0] = getSingleKey(KeyType.SUPPLY, KeyValueType.CONTRACT_ID, address(this));
    token.tokenKeys = keys;
    token.expiry = createAutoRenewExpiry(address(this), 7776000);

    (int rc, address created) = createNonFungibleToken{value: msg.value}(token);
    require(rc == HederaResponseCodes.SUCCESS, "Create failed");
}

function mintNFT(bytes memory metadata) external {
    bytes[] memory metas = new bytes[](1);
    metas[0] = metadata;
    (int rc, , int64[] memory serials) = mintToken(tokenAddress, 0, metas);
    require(rc == HederaResponseCodes.SUCCESS, "Mint failed");
}
KYC-Enabled Token

Treasury must self-grant KYC after creation:

// After token creation with KYC key
int kycRc = grantTokenKyc(tokenAddress, address(this));
require(kycRc == HederaResponseCodes.SUCCESS, "Self-KYC failed");

Response Code Handling

Always check response codes. SUCCESS = 22.

require(responseCode == HederaResponseCodes.SUCCESS, "Operation failed");

Common codes: See references/response-codes.md

Additional References

Comments

Markdown supported