HTSAdapterLib
Title: HTSAdapterLib
Authors: David Dada <daveproxy80@gmail.com> (https://github.com/dadadave80), Modified from hiero-ledger/hiero-contracts (https://github.com/hiero-ledger/hiero-contracts)
Logic + ERC-7201 storage for the diamond's Hedera Token Service account: associations, transfers of its own balances, and creation / mint / burn of tokens it holds the keys to.
All system-contract calls are plain calls from the diamond (a facet delegatecall frame): HTS sees
msg.sender == diamond, so the diamond's account is the one whose associations, balances, allowances,
and keys are checked. Because that frame IS a delegatecall frame, HTS activates only
delegatableContractId keys for the diamond wherever a key is actually verified, so every key this
library sets on a created token uses delegatableContractId = address(this).
MEASURED CAVEAT (hedera-testnet, consensus node 0.76.3, 2026-09-12): the shorter claim that a
contractId key on a diamond is simply dead is FALSE for the ordinary deployment shape. A
relay-deployed contract's own account key is contractId(self), and the dispatched child
transaction's payer is the diamond, so a contractId(<diamond>) token key is byte-identical to the
payer key and PreHandleContextImpl.requireKey elides it before verification — such a key mints
fine. delegatableContractId is a different protobuf oneof, so it is genuinely required, verified
and passed; it is also the only form that survives a diamond whose account key is not
contractId(self), a key nested in a KeyList/ThresholdKey, or a key naming another contract. That
is why this library sets it unconditionally rather than relying on the elision.
Functions
htsAdapterStorage
Returns the ERC-7201 storage struct for HTSAdapter.
function htsAdapterStorage() internal pure returns (HTSAdapterStorage storage $);Returns
| Name | Type | Description |
|---|---|---|
| $ | HTSAdapterStorage |
__HTSAdapter_init
Registers the IHTSAdapter ERC-165 interface.
Must be called between preInitializer / postInitializer.
function __HTSAdapter_init() internal;registerInterface
Writes true to the ERC-165 map slot for IHTSAdapter.
function registerInterface() internal;isAssociated
True if the diamond is associated with token (HIP-719 facade on the token address).
function isAssociated(address token) internal view returns (bool);Parameters
| Name | Type | Description |
|---|---|---|
| token | address |
Returns
| Name | Type | Description |
|---|---|---|
| <none> | bool |
isHTSToken
True if token is an HTS token.
function isHTSToken(address token) internal view returns (bool isToken);Parameters
| Name | Type | Description |
|---|---|---|
| token | address |
Returns
| Name | Type | Description |
|---|---|---|
| isToken | bool |
htsTokenType
HTS token type (0 fungible, 1 non-fungible); reverts HTSNotAToken for a non-token.
function htsTokenType(address token) internal view returns (int32 tokenType);Parameters
| Name | Type | Description |
|---|---|---|
| token | address |
Returns
| Name | Type | Description |
|---|---|---|
| tokenType | int32 |
createdTokens
The HTS tokens created by this diamond.
function createdTokens() internal view returns (address[] memory);Returns
| Name | Type | Description |
|---|---|---|
| <none> | address[] |
associateToken
Associates the diamond with token. Caller must hold HTS_MANAGER_ROLE.
function associateToken(address token) internal;Parameters
| Name | Type | Description |
|---|---|---|
| token | address |
dissociateToken
Dissociates the diamond from token. Caller must hold HTS_MANAGER_ROLE.
function dissociateToken(address token) internal;Parameters
| Name | Type | Description |
|---|---|---|
| token | address |
createFungibleToken
Creates a fungible token treasuried and key-controlled by the diamond. Caller must hold
HTS_MANAGER_ROLE. Forwards msg.value as the creation fee.
function createFungibleToken(
string calldata name,
string calldata symbol,
string calldata memo,
int32 decimals,
int64 initialSupply,
int64 maxSupply
) internal returns (address token);Parameters
| Name | Type | Description |
|---|---|---|
| name | string | |
| symbol | string | |
| memo | string | |
| decimals | int32 | |
| initialSupply | int64 | |
| maxSupply | int64 |
Returns
| Name | Type | Description |
|---|---|---|
| token | address |
createNonFungibleToken
Creates a non-fungible token treasuried and key-controlled by the diamond. Caller must hold
HTS_MANAGER_ROLE. Forwards msg.value as the creation fee.
function createNonFungibleToken(string calldata name, string calldata symbol, string calldata memo, int64 maxSupply)
internal
returns (address token);Parameters
| Name | Type | Description |
|---|---|---|
| name | string | |
| symbol | string | |
| memo | string | |
| maxSupply | int64 |
Returns
| Name | Type | Description |
|---|---|---|
| token | address |
transferToken
Transfers amount of token from the diamond to to. Caller must hold HTS_OPERATOR_ROLE.
function transferToken(address token, address to, int64 amount) internal;Parameters
| Name | Type | Description |
|---|---|---|
| token | address | |
| to | address | |
| amount | int64 |
transferTokenFrom
Spends the allowance from granted the diamond: moves amount of token from from to to.
Caller must hold HTS_OPERATOR_ROLE.
function transferTokenFrom(address token, address from, address to, int64 amount) internal;Parameters
| Name | Type | Description |
|---|---|---|
| token | address | |
| from | address | |
| to | address | |
| amount | int64 |
transferNFT
Transfers NFT serialNumber of token from the diamond to to. Caller must hold HTS_OPERATOR_ROLE.
function transferNFT(address token, address to, int64 serialNumber) internal;Parameters
| Name | Type | Description |
|---|---|---|
| token | address | |
| to | address | |
| serialNumber | int64 |
mintToken
Mints to the treasury (the diamond). Caller must hold HTS_OPERATOR_ROLE.
function mintToken(address token, int64 amount, bytes[] calldata metadata)
internal
returns (int64 newTotalSupply, int64[] memory serialNumbers);Parameters
| Name | Type | Description |
|---|---|---|
| token | address | |
| amount | int64 | |
| metadata | bytes[] |
Returns
| Name | Type | Description |
|---|---|---|
| newTotalSupply | int64 | |
| serialNumbers | int64[] |
burnToken
Burns from the treasury (the diamond). Caller must hold HTS_OPERATOR_ROLE.
function burnToken(address token, int64 amount, int64[] calldata serialNumbers)
internal
returns (int64 newTotalSupply);Parameters
| Name | Type | Description |
|---|---|---|
| token | address | |
| amount | int64 | |
| serialNumbers | int64[] |
Returns
| Name | Type | Description |
|---|---|---|
| newTotalSupply | int64 |
_tokenTemplate
Builds the create-token template: diamond = treasury + auto-renew account, admin + supply keys as
delegatableContractId(diamond) (the ONLY key form a facet call can activate), 90-day auto-renew.
function _tokenTemplate(string calldata name, string calldata symbol, string calldata memo, int64 maxSupply)
private
view
returns (IHederaTokenService.HederaToken memory t);Parameters
| Name | Type | Description |
|---|---|---|
| name | string | |
| symbol | string | |
| memo | string | |
| maxSupply | int64 |
Returns
| Name | Type | Description |
|---|---|---|
| t | IHederaTokenService.HederaToken |
_decodeCreate
Decodes a create* return; maps a failed frame to UNKNOWN like hiero-contracts' helper does.
function _decodeCreate(bytes4 selector, bool ok, bytes memory ret) private pure returns (address token);Parameters
| Name | Type | Description |
|---|---|---|
| selector | bytes4 | |
| ok | bool | |
| ret | bytes |
Returns
| Name | Type | Description |
|---|---|---|
| token | address |
_callForCode
Plain call into HTS returning the response code (UNKNOWN when the frame itself failed).
function _callForCode(bytes memory data) private returns (int64 code);Parameters
| Name | Type | Description |
|---|---|---|
| data | bytes |
Returns
| Name | Type | Description |
|---|---|---|
| code | int64 |
_staticcall
staticcall into HTS for the view-classified getters; a halted frame surfaces as HTSCallFailed.
function _staticcall(bytes memory data) private view returns (bytes memory ret);Parameters
| Name | Type | Description |
|---|---|---|
| data | bytes |
Returns
| Name | Type | Description |
|---|---|---|
| ret | bytes |
_check
Maps an HTS response code to the typed error for selector; no-op on SUCCESS.
function _check(bytes4 selector, int64 code, address token, address account) private pure;Parameters
| Name | Type | Description |
|---|---|---|
| selector | bytes4 | |
| code | int64 | |
| token | address | |
| account | address |