Hedera
  • Welcome to Hedera — let’s build the future
  • Getting Started
    • Environment Setup
    • Web2 Developers
      • Transfer HBAR
      • Create a Token
      • Create a Topic
    • EVM Developers
      • Deploy a Contract
  • Tutorials
    • Smart Contracts
      • How to Mint & Burn an ERC-721 Token Using Hardhat and Ethers (Part 1)
      • How to Set Access Control, a Token URI, Pause, and Transfer an ERC-721 Token Using Hardhat (Part 2)
      • How to Verify a Smart Contract on HashScan
      • Deploy a Smart Contract Using Remix
      • Deploy a Smart Contract Using Hardhat and Hiero JSON-RPC Relay
      • Deploy Your First Smart Contract
      • Deploy a Contract Using the Hedera Token Service
      • Send and Receive HBAR Using Solidity Smart Contracts
      • Deploy By Leveraging Ethereum Developer Tools On Hedera
      • Deploy a Subgraph Using The Graph and Hedera JSON-RPC Relay
      • Deploy Smart Contracts on Hedera Using Truffle
      • The Power of Native Hedera Tokens as ERC-20 Tokens: A step-by-step guide
      • HTS x EVM - Part 1: How to Mint NFTs
      • HTS x EVM - Part 2: KYC & Update
      • HTS x EVM - Part 3: How to Pause, Freeze, Wipe, and Delete NFTs
      • Hedera Smart Contracts Workshop
        • Setup
        • Solidity
        • Hedera SDK JS
        • Hardhat and EthersJs
        • Outro
      • Foundry
        • How to Setup Foundry and Write a Basic Unit Test
        • How to Deploy and Verify a Hedera Smart Contract with Foundry
        • How to Test A Solidity Event
        • How to Fork Testnet on Latest Block
    • Consensus
      • Submit Your First Message
      • Submit Message to Private Topic
      • Query Messages with Mirror Node
    • Tokens
      • Create and Transfer Your First NFT
      • Create and Transfer Your First Fungible Token
      • Create and Transfer an NFT using a Solidity Contract
      • Structure Your Token Metadata Using JSON Schema V2
      • Hedera Token Service - Part 1: How to Mint NFTs
      • Hedera Token Service - Part 2: KYC, Update, and Scheduled Transactions
      • Hedera Token Service - Part 3: How to Pause, Freeze, Wipe, and Delete NFTs
      • Create Your First Frictionless Airdrop Campaign
    • Local Node
      • How to Run Hedera Local Node in a Cloud Development Environment (CDE)
        • Run a Local Node in Gitpod
        • Run a Local Node in Codespaces
      • How to Set Up a Hedera Local Node
      • Set Up a Hedera Local Node using the NPM CLI
    • More Tutorials
      • Create and Fund Your Hedera Testnet Account
      • How to Create a Personal Access Token (API Key) on the Hedera Portal
      • How to Auto-Create Hedera Accounts with HBAR and Token Transfers
      • How to Configure a Mirror Node and Query Data
      • How to Generate a Random Number on Hedera
      • Get Started with the Hedera Consensus Service Fabric Plugin
        • Virtual Environment Setup
      • Schedule Your First Transaction
      • How to Connect to Hedera Networks Over RPC
        • Configuring Hashio RPC endpoints
        • Configuring Hiero JSON-RPC Relay endpoints
        • Configuring Validation Cloud RPC endpoints
      • JavaScript Testing
      • Create a Hedera DApp Integrated with WalletConnect
      • How to Connect MetaMask to Hedera
    • Demo Applications
    • Starter Projects
    • Building on Hedera (course)
  • Networks
    • Mainnet
      • Mainnet Accounts
      • Mainnet Consensus Nodes
        • Node Requirements
          • FAQ
      • Fees
        • Transaction Records
    • Testnets
      • Testnet Accounts
      • Testnet Consensus Nodes
    • Localnet
      • Single Node Configuration
      • Multinode Configuration
    • Network Explorers and Tools
    • Release Notes
      • Consensus Node
      • Hedera Mirror Node
  • Core Concepts
    • Accounts
      • Account Creation
      • Auto Account Creation
      • Account Properties
    • Keys and Signatures
    • Schedule Transaction
    • Smart Contracts
      • Understanding Hedera's EVM Differences and Compatibility
        • For EVM Developers Migrating to Hedera
          • Accounts, Signature Verification & Keys (ECDSA vs. ED25519)
          • JSON-RPC Relay and EVM Tooling
          • Token Management with Hedera Token Service
          • Decimal Handling (8 vs. 18 Decimals)
          • Handling HBAR Transfers in Contracts
        • For Hedera-Native Developers Adding Smart Contract Functionality
          • Integrating ED25519 Accounts and Advanced Features Into Smart Contracts
          • JSON-RPC Relay and State Queries
          • Extending Token Management with Smart Contracts
      • Creating Smart Contracts
      • Compiling Smart Contracts
      • System Smart Contracts
        • Hedera Account Service
        • Hedera Schedule Service
      • Gas and Fees
      • JSON-RPC Relay
      • Deploying Smart Contracts
      • Smart Contract Addresses
      • Verifying Smart Contracts
      • Smart Contract Traceability
      • Tokens Managed by Smart Contracts
        • ERC-20 (Fungible Tokens)
        • ERC-721 (Non-Fungible Token)
        • ERC-3643 Real World Assets (RWA)
        • ERC-1363 (Payable Tokens)
        • Hedera Token Service System Contract
      • Wrapped HBAR (WHBAR)
      • Smart Contract Rent
      • Smart Contract Security
      • EVM Archive Node Queries
    • Tokens
      • Tokenization on Hedera
      • Hedera Token Service (HTS) Native Tokenization
        • Token Types and ID Formats
        • Token Properties
        • Token Creation
        • Custom Fee Schedule
        • Token Airdrops
      • ERC/EVM-Compatible Tokenization
      • Hybrid (HTS + EVM ) Tokenization
    • Staking
      • Staking Program
      • Stake HBAR
    • Hashgraph Consensus Algorithm
      • Gossip About Gossip
      • Virtual Voting
    • Transactions and Queries
      • Transaction Properties
    • State and History
    • Mirror Nodes
      • Hedera Mirror Node
      • One Click Mirror Node Deployment
      • Run Your Own Mirror Node
        • Run Your Own Mirror Node with Google Cloud Storage (GCS)
        • Run Your Mirror Node with Amazon Web Services S3 (AWS)
  • Open Source Solutions and Integrations
    • AI Tools for Developers
      • Hedera AI Agent Kit
      • ElizaOS Plugin for Hedera
      • Hedera Hivemind
      • Kapa AI
    • Asset Tokenization Studio (ATS)
      • Web User Interface (UI)
      • Frequently Asked Questions (FAQs)
    • HashioDAO
      • Governance Token DAO
      • NFT DAO
      • Multisig DAO
      • DAO Proposals
      • Local Environment Setup
    • Hedera CLI
    • Hedera Custodians Library
      • How to use it
    • Hedera Developer Playground
    • Hedera Wallet Snap By MetaMask
      • Hedera Wallet Snap Documentation
      • Tutorial: MetaMask Snaps – What Are They and How to Use Them
    • Interoperability and Bridging
      • LayerZero
    • NFT Studio
      • Airdrop List Verifier
      • Metadata Validator
      • NFT Rarity Inspector
      • NFT Token Holders List Builder
      • NFT Risk Calculator
      • Token Balance Snapshot
      • Hedera NFT SDK
    • Oracle Networks
      • Chainlink Oracles
      • Pyth Oracles
      • Supra Oracles
    • Stablecoin Studio
      • Core Concepts
      • Web UI Application
      • CLI Management
      • TypeScript SDK
    • Hedera Guardian
    • Hedera WalletConnect
  • SDKs & APIs
    • SDKs
      • Build Your Hedera Client
      • Set Up Your Local Network
      • Network Address Book
      • Keys
        • Generate a new key pair
        • Import an existing key
        • Create a key list
        • Create a threshold key
        • Generate a mnemonic phrase
        • Recover keys from a mnemonic phrase
      • HBAR
      • Specialized Types
      • Pseudorandom Number Generator
      • Transactions
        • Create a Batch Transaction
        • Transaction ID
        • Modify transaction fields
        • Create an unsigned transaction
        • Manually sign a transaction
        • Submit a transaction
        • Sign a multisignature transaction
        • Get a transaction receipt
        • Get a transaction record
      • Schedule Transaction
        • Schedule ID
        • Create a schedule transaction
        • Sign a scheduled transaction
        • Delete a schedule transaction
        • Get schedule info
        • Network Response Messages
      • Queries
      • General Network Response Messages
      • Accounts and HBAR
        • Create an account
        • Update an account
        • Transfer cryptocurrency
        • Approve an allowance
        • Delete an allowance
        • Delete an account
        • Get account balance
        • Get account info
        • Network Response Messages
      • Consensus Service
        • Create a topic
        • Update a topic
        • Submit a message
        • Delete a topic
        • Get topic messages
        • Get topic info
        • Network Response
      • Token Service
        • Token ID
        • NFT ID
        • Token types
        • Create a token
        • Custom token fees
        • Update a token
        • Update token custom fees
        • Update NFT metadata
        • Transfer tokens
        • Airdrop a token
        • Claim a token
        • Cancel a token
        • Reject a token
        • Delete a token
        • Mint a token
        • Burn a token
        • Freeze an account
        • Unfreeze an account
        • Enable KYC account flag
        • Disable KYC account flag
        • Associate tokens to an account
        • Dissociate tokens from an account
        • Pause a token
        • Unpause a token
        • Wipe a token
        • Atomic swaps
        • Get account token balance
        • Get token info
        • Get NFT info
        • Network Response Messages
      • File Service
        • Create a file
        • Append to a file
        • Update a file
        • Delete a file
        • Get file contents
        • Get file info
        • Network Response Messages
      • Smart Contract Service
        • Delegate Contract ID
        • Create a smart contract
        • Update a smart contract
        • Delete a smart contract
        • Call a smart contract function
        • Ethereum transaction
        • Get a smart contract function
        • Get smart contract bytecode
        • Get smart contract info
        • Hedera Service Solidity Libraries
        • Network Response Messages
      • Signature Provider
        • Provider
        • Signer
        • Wallet
        • Local Provider
    • Mirror Node REST API
      • Accounts
      • Balances
      • Blocks
      • Schedule Transactions
      • Smart Contracts
      • Tokens
      • Topics
      • Transactions
      • Network
    • Hedera Consensus Service gRPC API
    • Hedera APIs
      • Basic Types
        • AccountAmount
        • AccountID
        • ContractID
        • CryptoAllowance
        • CurrentAndNextFeeSchedule
        • FeeComponents
        • FeeData
        • FeeSchedule
        • FileID
        • Fraction
        • HederaFunctionality
        • Key
        • KeyList
        • NftAllowance
        • NftTransfer
        • NodeAddress
        • NodeAddressBook
        • RealmID
        • ScheduleID
        • SemanticVersion
        • ServicesConfigurationList
        • ServiceEndpoint
        • Setting
        • ShardID
        • Signature
        • SignatureList
        • SignatureMap
        • SignaturePair
        • SubType
        • TransferList
        • TransactionID
        • ThresholdKey
        • ThresholdSignature
        • TokenAllowance
        • TokenBalance
        • TokenBalances
        • TokenFreezeStatus
        • TokenPauseStatus
        • TokenID
        • TokenKycStatus
        • TokenRelationship
        • TokenTransferList
        • TokenType
        • TokenSupplyType
        • TopicID
        • TransactionFeeSchedule
      • Cryptocurrency Accounts
        • CryptoService
        • CryptApproveAllowance
        • CryptoDeleteAllowance
        • CryptoCreate
        • CryptoTransfer
        • CryptoUpdate
        • CryptoDelete
        • CryptoGetAccountBalance
        • CryptoGetAccountRecords
        • CryptoGetInfo
        • CryptoGetStakers
      • Consensus Service
        • Consensus Service
        • ConsensusCreateTopic
        • ConsensusUpdateTopic
        • ConsensusSubmitMessage
        • ConsensusDeleteTopic
        • ConsensusTopicInfo
        • ConsensusGetTopicInfo
      • Schedule Service
        • ScheduleService
        • SchedulableTransactionBody
        • ScheduleCreate
        • ScheduleDelete
        • ScheduleSign
        • ScheduleGetInfo
      • Token Service
        • TokenService
        • CustomFees
          • AssessedCustomFee
          • CustomFee
          • FractionalFee
          • FixedFee
          • RoyaltyFee
        • TokenCreate
        • TokenUpdate
        • TokenFeeScheduleUpdate
        • TokenDelete
        • TokenMint
        • TokenBurn
        • TokenFreezeAccount
        • TokenUnfreezeAccount
        • TokenGrantKyc
        • TokenRevokeKyc
        • TokenAssociate
        • TokenDissociate
        • TokenWipeAccount
        • TokenPause
        • TokenUnpause
        • TokenGetInfo
        • TokenGetNftInfo
        • TokenGetNftInfos
        • TokenGetAccountNftInfo
      • File Service
        • FileService
        • FileCreate
        • FileAppend
        • FileUpdate
        • FileDelete
        • FileGetContents
        • FileGetInfo
      • Smart Contracts
        • SmartContractService
        • ContractCall
        • ContractCallLocal
        • ContractCreate
        • ContractUpdate
        • ContractDelete
        • ContractGetByteCode
        • ContractGetInfo
        • ContractGetRecords
      • Miscellaneous
        • Duration
        • ExchangeRate
        • Freeze
        • FreezeType
        • GetByKey
        • GetBySolidityID
        • NetworkGetVersionInfo
        • NetworkService
        • Query
        • QueryHeader
        • Response
        • ResponseCode
        • ResponseHeader
        • SystemDelete
        • SystemUndelete
        • TimeStamp
        • Transaction
        • TransactionBody
        • TransactionContents
        • TransactionGetFastRecord
        • TransactionGetReceipt
        • TransactionGetRecord
        • TransactionReceipt
        • TransactionRecord
        • TransactionResponse
        • UncheckedSubmit
    • Hedera Status API
  • Support & Community
    • Glossary
    • Contributing to Hedera documentation
      • Contribution Guidelines
        • Creating Issues
        • Creating Pull Requests
        • Hedera Improvement Proposal (HIP)
        • Submit Demo Applications
      • Style Guide
        • Understanding different types of documentation
        • Use of HBAR and tinybars
        • Use of web2 and web3
        • Language and grammar
        • Formatting
        • Punctuation
        • GitBook Markdown Syntax
    • Discord
    • GitHub
    • Stack Overflow
    • Hedera Blog
    • Bug Bounty
    • Hedera Help
    • Documentation Survey
    • Meetups
    • Brand Guidelines
    • Status Page
Powered by GitBook
LogoLogo

INTRODUCTION

  • Fees
  • Core Concepts
  • Network Information

TOOLS

  • Bridge
  • Oracles
  • Explorers
  • Developer Portal & Faucet

RESOURCES

  • Status
  • Bug Bounty
  • Build on Hedera (course)
  • Documentation Survey
On this page
  • Summary
  • Prerequisites
  • 1. Create Your "HTS" Smart Contract
  • 2. Store the Smart Contract Bytecode on Hedera
  • 3. Deploy a Hedera Smart Contract
  • 4. Call the tokenAssociate Contract Function
  • 5. Call the approveTokenAllowance Function
  • 6. Call the tokenTransfer Contract Function
  • Code Check ✅
  • Additional Resources

Was this helpful?

Edit on GitHub
  1. Tutorials
  2. Smart Contracts

Deploy a Contract Using the Hedera Token Service

PreviousDeploy Your First Smart ContractNextSend and Receive HBAR Using Solidity Smart Contracts

Last updated 1 month ago

Was this helpful?

Summary

In this example, you will learn how to create a Solidity contract that interacts with the Hedera Token Service (HTS). The initial release of this feature supports token mint, burn, associate, dissociate, and transfer transactions.

The example does not cover the environment setup or creating certain variables that may be seen in the code blocks. The full coding example can be found at the end of the page.

Smart contract entity auto renewal and expiry will be enabled in a future release. Please check out for more information.


Prerequisites

We recommend you complete the following introduction to get a basic understanding of Hedera transactions. This example does not build upon the previous examples.

  • Get a .

  • Set up your environment .


1. Create Your "HTS" Smart Contract

In this example, you will associate a token to an account and transfer tokens to the associated account by interacting with the HTS contract deployed to Hedera. The HTS contract has three functions that allow you to associate, transfer, and dissociate tokens from a Hedera account.

  • tokenAssociate

  • tokenTransfer

  • tokenDissociate

The HTS.sol will serve as a reference to the contract that was compiled. The HTS.json file contains the data.bytecode.object field that will be used to store the contract bytecode in a file on the Hedera network.

// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.6.12;

import "./HederaTokenService.sol";
import "./HederaResponseCodes.sol";


contract HTS is HederaTokenService {

    function tokenAssociate(address sender, address tokenAddress) external {
        int response = HederaTokenService.associateToken(sender, tokenAddress);

        if (response != HederaResponseCodes.SUCCESS) {
            revert ("Associate Failed");
        }
    }

    function tokenTransfer(address tokenId, address fromAccountId , address toAccountId , int64 tokenAmount) external {
        int response = HederaTokenService.transferToken(tokenId, fromAccountId, toAccountId, tokenAmount);

        if (response != HederaResponseCodes.SUCCESS) {
            revert ("Transfer Failed");
        }
    }

    function tokenDissociate(address sender, address tokenAddress) external {
        int response = HederaTokenService.dissociateToken(sender, tokenAddress);

        if (response != HederaResponseCodes.SUCCESS) {
            revert ("Dissociate Failed");
        }
    }
}
{
  "deploy": {
    "VM:-": {
      "linkReferences": {},
      "autoDeployLib": true
    },
    "main:1": {
      "linkReferences": {},
      "autoDeployLib": true
    },
    "ropsten:3": {
      "linkReferences": {},
      "autoDeployLib": true
    },
    "rinkeby:4": {
      "linkReferences": {},
      "autoDeployLib": true
    },
    "kovan:42": {
      "linkReferences": {},
      "autoDeployLib": true
    },
    "görli:5": {
      "linkReferences": {},
      "autoDeployLib": true
    },
    "Custom": {
      "linkReferences": {},
      "autoDeployLib": true
    }
  },
  "data": {
    "bytecode": {
      "linkReferences": {},
      "object": "608060405234801561001057600080fd5b5061089d806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80633a04033c146100465780634753b51b146100d75780637f6314d01461013b575b600080fd5b6100d56004803603608081101561005c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560070b906020019092919050505061019f565b005b610139600480360360408110156100ed57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061022f565b005b61019d6004803603604081101561015157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506102bb565b005b60006101ad85858585610347565b9050601660030b8114610228576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f5472616e73666572204661696c6564000000000000000000000000000000000081525060200191505060405180910390fd5b5050505050565b600061023b8383610519565b9050601660030b81146102b6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f446973736f6369617465204661696c656400000000000000000000000000000081525060200191505060405180910390fd5b505050565b60006102c783836106c0565b9050601660030b8114610342576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f4173736f6369617465204661696c65640000000000000000000000000000000081525060200191505060405180910390fd5b505050565b600080606061016773ffffffffffffffffffffffffffffffffffffffff1663eca3691760e01b88888888604051602401808573ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018260070b8152602001945050505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040518082805190602001908083835b6020831061046b5780518252602082019150602081019050602083039250610448565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d80600081146104cd576040519150601f19603f3d011682016040523d82523d6000602084013e6104d2565b606091505b5091509150816104e357601561050a565b8080602001905160208110156104f857600080fd5b81019080805190602001909291905050505b60030b92505050949350505050565b600080606061016773ffffffffffffffffffffffffffffffffffffffff1663099794e860e01b8686604051602401808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff16815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040518082805190602001908083835b6020831061061457805182526020820191506020810190506020830392506105f1565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114610676576040519150601f19603f3d011682016040523d82523d6000602084013e61067b565b606091505b50915091508161068c5760156106b3565b8080602001905160208110156106a157600080fd5b81019080805190602001909291905050505b60030b9250505092915050565b600080606061016773ffffffffffffffffffffffffffffffffffffffff166349146bde60e01b8686604051602401808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff16815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040518082805190602001908083835b602083106107bb5780518252602082019150602081019050602083039250610798565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d806000811461081d576040519150601f19603f3d011682016040523d82523d6000602084013e610822565b606091505b50915091508161083357601561085a565b80806020019051602081101561084857600080fd5b81019080805190602001909291905050505b60030b925050509291505056fea264697066735822122068ba1095e27dfaf338e8ee9d0914f328fe6a23627ce5b8245b5fd09275ba76d964736f6c634300060c0033",
      "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x89D DUP1 PUSH2 0x20 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0x41 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x3A04033C EQ PUSH2 0x46 JUMPI DUP1 PUSH4 0x4753B51B EQ PUSH2 0xD7 JUMPI DUP1 PUSH4 0x7F6314D0 EQ PUSH2 0x13B JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xD5 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x80 DUP2 LT ISZERO PUSH2 0x5C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH1 0x7 SIGNEXTEND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x19F JUMP JUMPDEST STOP JUMPDEST PUSH2 0x139 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0xED JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x22F JUMP JUMPDEST STOP JUMPDEST PUSH2 0x19D PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x151 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x2BB JUMP JUMPDEST STOP JUMPDEST PUSH1 0x0 PUSH2 0x1AD DUP6 DUP6 DUP6 DUP6 PUSH2 0x347 JUMP JUMPDEST SWAP1 POP PUSH1 0x16 PUSH1 0x3 SIGNEXTEND DUP2 EQ PUSH2 0x228 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0xF DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x5472616E73666572204661696C65640000000000000000000000000000000000 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x23B DUP4 DUP4 PUSH2 0x519 JUMP JUMPDEST SWAP1 POP PUSH1 0x16 PUSH1 0x3 SIGNEXTEND DUP2 EQ PUSH2 0x2B6 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x11 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x446973736F6369617465204661696C6564000000000000000000000000000000 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x2C7 DUP4 DUP4 PUSH2 0x6C0 JUMP JUMPDEST SWAP1 POP PUSH1 0x16 PUSH1 0x3 SIGNEXTEND DUP2 EQ PUSH2 0x342 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x10 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x4173736F6369617465204661696C656400000000000000000000000000000000 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x60 PUSH2 0x167 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH4 0xECA36917 PUSH1 0xE0 SHL DUP9 DUP9 DUP9 DUP9 PUSH1 0x40 MLOAD PUSH1 0x24 ADD DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP3 PUSH1 0x7 SIGNEXTEND DUP2 MSTORE PUSH1 0x20 ADD SWAP5 POP POP POP POP POP PUSH1 0x40 MLOAD PUSH1 0x20 DUP2 DUP4 SUB SUB DUP2 MSTORE SWAP1 PUSH1 0x40 MSTORE SWAP1 PUSH28 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF NOT AND PUSH1 0x20 DUP3 ADD DUP1 MLOAD PUSH28 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP4 DUP2 DUP4 AND OR DUP4 MSTORE POP POP POP POP PUSH1 0x40 MLOAD DUP1 DUP3 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 JUMPDEST PUSH1 0x20 DUP4 LT PUSH2 0x46B JUMPI DUP1 MLOAD DUP3 MSTORE PUSH1 0x20 DUP3 ADD SWAP2 POP PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH1 0x20 DUP4 SUB SWAP3 POP PUSH2 0x448 JUMP JUMPDEST PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB DUP1 NOT DUP3 MLOAD AND DUP2 DUP5 MLOAD AND DUP1 DUP3 OR DUP6 MSTORE POP POP POP POP POP POP SWAP1 POP ADD SWAP2 POP POP PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP7 GAS CALL SWAP2 POP POP RETURNDATASIZE DUP1 PUSH1 0x0 DUP2 EQ PUSH2 0x4CD JUMPI PUSH1 0x40 MLOAD SWAP2 POP PUSH1 0x1F NOT PUSH1 0x3F RETURNDATASIZE ADD AND DUP3 ADD PUSH1 0x40 MSTORE RETURNDATASIZE DUP3 MSTORE RETURNDATASIZE PUSH1 0x0 PUSH1 0x20 DUP5 ADD RETURNDATACOPY PUSH2 0x4D2 JUMP JUMPDEST PUSH1 0x60 SWAP2 POP JUMPDEST POP SWAP2 POP SWAP2 POP DUP2 PUSH2 0x4E3 JUMPI PUSH1 0x15 PUSH2 0x50A JUMP JUMPDEST DUP1 DUP1 PUSH1 0x20 ADD SWAP1 MLOAD PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x4F8 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP JUMPDEST PUSH1 0x3 SIGNEXTEND SWAP3 POP POP POP SWAP5 SWAP4 POP POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x60 PUSH2 0x167 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH4 0x99794E8 PUSH1 0xE0 SHL DUP7 DUP7 PUSH1 0x40 MLOAD PUSH1 0x24 ADD DUP1 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP3 POP POP POP PUSH1 0x40 MLOAD PUSH1 0x20 DUP2 DUP4 SUB SUB DUP2 MSTORE SWAP1 PUSH1 0x40 MSTORE SWAP1 PUSH28 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF NOT AND PUSH1 0x20 DUP3 ADD DUP1 MLOAD PUSH28 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP4 DUP2 DUP4 AND OR DUP4 MSTORE POP POP POP POP PUSH1 0x40 MLOAD DUP1 DUP3 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 JUMPDEST PUSH1 0x20 DUP4 LT PUSH2 0x614 JUMPI DUP1 MLOAD DUP3 MSTORE PUSH1 0x20 DUP3 ADD SWAP2 POP PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH1 0x20 DUP4 SUB SWAP3 POP PUSH2 0x5F1 JUMP JUMPDEST PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB DUP1 NOT DUP3 MLOAD AND DUP2 DUP5 MLOAD AND DUP1 DUP3 OR DUP6 MSTORE POP POP POP POP POP POP SWAP1 POP ADD SWAP2 POP POP PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP7 GAS CALL SWAP2 POP POP RETURNDATASIZE DUP1 PUSH1 0x0 DUP2 EQ PUSH2 0x676 JUMPI PUSH1 0x40 MLOAD SWAP2 POP PUSH1 0x1F NOT PUSH1 0x3F RETURNDATASIZE ADD AND DUP3 ADD PUSH1 0x40 MSTORE RETURNDATASIZE DUP3 MSTORE RETURNDATASIZE PUSH1 0x0 PUSH1 0x20 DUP5 ADD RETURNDATACOPY PUSH2 0x67B JUMP JUMPDEST PUSH1 0x60 SWAP2 POP JUMPDEST POP SWAP2 POP SWAP2 POP DUP2 PUSH2 0x68C JUMPI PUSH1 0x15 PUSH2 0x6B3 JUMP JUMPDEST DUP1 DUP1 PUSH1 0x20 ADD SWAP1 MLOAD PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x6A1 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP JUMPDEST PUSH1 0x3 SIGNEXTEND SWAP3 POP POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x60 PUSH2 0x167 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH4 0x49146BDE PUSH1 0xE0 SHL DUP7 DUP7 PUSH1 0x40 MLOAD PUSH1 0x24 ADD DUP1 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP3 POP POP POP PUSH1 0x40 MLOAD PUSH1 0x20 DUP2 DUP4 SUB SUB DUP2 MSTORE SWAP1 PUSH1 0x40 MSTORE SWAP1 PUSH28 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF NOT AND PUSH1 0x20 DUP3 ADD DUP1 MLOAD PUSH28 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP4 DUP2 DUP4 AND OR DUP4 MSTORE POP POP POP POP PUSH1 0x40 MLOAD DUP1 DUP3 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 JUMPDEST PUSH1 0x20 DUP4 LT PUSH2 0x7BB JUMPI DUP1 MLOAD DUP3 MSTORE PUSH1 0x20 DUP3 ADD SWAP2 POP PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH1 0x20 DUP4 SUB SWAP3 POP PUSH2 0x798 JUMP JUMPDEST PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB DUP1 NOT DUP3 MLOAD AND DUP2 DUP5 MLOAD AND DUP1 DUP3 OR DUP6 MSTORE POP POP POP POP POP POP SWAP1 POP ADD SWAP2 POP POP PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP7 GAS CALL SWAP2 POP POP RETURNDATASIZE DUP1 PUSH1 0x0 DUP2 EQ PUSH2 0x81D JUMPI PUSH1 0x40 MLOAD SWAP2 POP PUSH1 0x1F NOT PUSH1 0x3F RETURNDATASIZE ADD AND DUP3 ADD PUSH1 0x40 MSTORE RETURNDATASIZE DUP3 MSTORE RETURNDATASIZE PUSH1 0x0 PUSH1 0x20 DUP5 ADD RETURNDATACOPY PUSH2 0x822 JUMP JUMPDEST PUSH1 0x60 SWAP2 POP JUMPDEST POP SWAP2 POP SWAP2 POP DUP2 PUSH2 0x833 JUMPI PUSH1 0x15 PUSH2 0x85A JUMP JUMPDEST DUP1 DUP1 PUSH1 0x20 ADD SWAP1 MLOAD PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x848 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP JUMPDEST PUSH1 0x3 SIGNEXTEND SWAP3 POP POP POP SWAP3 SWAP2 POP POP JUMP INVALID LOG2 PUSH5 0x6970667358 0x22 SLT KECCAK256 PUSH9 0xBA1095E27DFAF338E8 0xEE SWAP14 MULMOD EQ RETURN 0x28 INVALID PUSH11 0x23627CE5B8245B5FD09275 0xBA PUSH23 0xD964736F6C634300060C00330000000000000000000000 ",
      "sourceMap": "138:923:0:-:0;;;;;;;;;;;;;;;;;;;"
    },
    "deployedBytecode": {
      "immutableReferences": {},
      "linkReferences": {},
      "object": "608060405234801561001057600080fd5b50600436106100415760003560e01c80633a04033c146100465780634753b51b146100d75780637f6314d01461013b575b600080fd5b6100d56004803603608081101561005c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560070b906020019092919050505061019f565b005b610139600480360360408110156100ed57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061022f565b005b61019d6004803603604081101561015157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506102bb565b005b60006101ad85858585610347565b9050601660030b8114610228576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f5472616e73666572204661696c6564000000000000000000000000000000000081525060200191505060405180910390fd5b5050505050565b600061023b8383610519565b9050601660030b81146102b6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f446973736f6369617465204661696c656400000000000000000000000000000081525060200191505060405180910390fd5b505050565b60006102c783836106c0565b9050601660030b8114610342576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f4173736f6369617465204661696c65640000000000000000000000000000000081525060200191505060405180910390fd5b505050565b600080606061016773ffffffffffffffffffffffffffffffffffffffff1663eca3691760e01b88888888604051602401808573ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018260070b8152602001945050505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040518082805190602001908083835b6020831061046b5780518252602082019150602081019050602083039250610448565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d80600081146104cd576040519150601f19603f3d011682016040523d82523d6000602084013e6104d2565b606091505b5091509150816104e357601561050a565b8080602001905160208110156104f857600080fd5b81019080805190602001909291905050505b60030b92505050949350505050565b600080606061016773ffffffffffffffffffffffffffffffffffffffff1663099794e860e01b8686604051602401808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff16815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040518082805190602001908083835b6020831061061457805182526020820191506020810190506020830392506105f1565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114610676576040519150601f19603f3d011682016040523d82523d6000602084013e61067b565b606091505b50915091508161068c5760156106b3565b8080602001905160208110156106a157600080fd5b81019080805190602001909291905050505b60030b9250505092915050565b600080606061016773ffffffffffffffffffffffffffffffffffffffff166349146bde60e01b8686604051602401808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff16815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040518082805190602001908083835b602083106107bb5780518252602082019150602081019050602083039250610798565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d806000811461081d576040519150601f19603f3d011682016040523d82523d6000602084013e610822565b606091505b50915091508161083357601561085a565b80806020019051602081101561084857600080fd5b81019080805190602001909291905050505b60030b925050509291505056fea264697066735822122068ba1095e27dfaf338e8ee9d0914f328fe6a23627ce5b8245b5fd09275ba76d964736f6c634300060c0033",
      "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0x41 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x3A04033C EQ PUSH2 0x46 JUMPI DUP1 PUSH4 0x4753B51B EQ PUSH2 0xD7 JUMPI DUP1 PUSH4 0x7F6314D0 EQ PUSH2 0x13B JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xD5 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x80 DUP2 LT ISZERO PUSH2 0x5C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH1 0x7 SIGNEXTEND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x19F JUMP JUMPDEST STOP JUMPDEST PUSH2 0x139 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0xED JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x22F JUMP JUMPDEST STOP JUMPDEST PUSH2 0x19D PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x151 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x2BB JUMP JUMPDEST STOP JUMPDEST PUSH1 0x0 PUSH2 0x1AD DUP6 DUP6 DUP6 DUP6 PUSH2 0x347 JUMP JUMPDEST SWAP1 POP PUSH1 0x16 PUSH1 0x3 SIGNEXTEND DUP2 EQ PUSH2 0x228 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0xF DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x5472616E73666572204661696C65640000000000000000000000000000000000 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x23B DUP4 DUP4 PUSH2 0x519 JUMP JUMPDEST SWAP1 POP PUSH1 0x16 PUSH1 0x3 SIGNEXTEND DUP2 EQ PUSH2 0x2B6 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x11 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x446973736F6369617465204661696C6564000000000000000000000000000000 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x2C7 DUP4 DUP4 PUSH2 0x6C0 JUMP JUMPDEST SWAP1 POP PUSH1 0x16 PUSH1 0x3 SIGNEXTEND DUP2 EQ PUSH2 0x342 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x10 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x4173736F6369617465204661696C656400000000000000000000000000000000 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x60 PUSH2 0x167 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH4 0xECA36917 PUSH1 0xE0 SHL DUP9 DUP9 DUP9 DUP9 PUSH1 0x40 MLOAD PUSH1 0x24 ADD DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP3 PUSH1 0x7 SIGNEXTEND DUP2 MSTORE PUSH1 0x20 ADD SWAP5 POP POP POP POP POP PUSH1 0x40 MLOAD PUSH1 0x20 DUP2 DUP4 SUB SUB DUP2 MSTORE SWAP1 PUSH1 0x40 MSTORE SWAP1 PUSH28 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF NOT AND PUSH1 0x20 DUP3 ADD DUP1 MLOAD PUSH28 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP4 DUP2 DUP4 AND OR DUP4 MSTORE POP POP POP POP PUSH1 0x40 MLOAD DUP1 DUP3 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 JUMPDEST PUSH1 0x20 DUP4 LT PUSH2 0x46B JUMPI DUP1 MLOAD DUP3 MSTORE PUSH1 0x20 DUP3 ADD SWAP2 POP PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH1 0x20 DUP4 SUB SWAP3 POP PUSH2 0x448 JUMP JUMPDEST PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB DUP1 NOT DUP3 MLOAD AND DUP2 DUP5 MLOAD AND DUP1 DUP3 OR DUP6 MSTORE POP POP POP POP POP POP SWAP1 POP ADD SWAP2 POP POP PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP7 GAS CALL SWAP2 POP POP RETURNDATASIZE DUP1 PUSH1 0x0 DUP2 EQ PUSH2 0x4CD JUMPI PUSH1 0x40 MLOAD SWAP2 POP PUSH1 0x1F NOT PUSH1 0x3F RETURNDATASIZE ADD AND DUP3 ADD PUSH1 0x40 MSTORE RETURNDATASIZE DUP3 MSTORE RETURNDATASIZE PUSH1 0x0 PUSH1 0x20 DUP5 ADD RETURNDATACOPY PUSH2 0x4D2 JUMP JUMPDEST PUSH1 0x60 SWAP2 POP JUMPDEST POP SWAP2 POP SWAP2 POP DUP2 PUSH2 0x4E3 JUMPI PUSH1 0x15 PUSH2 0x50A JUMP JUMPDEST DUP1 DUP1 PUSH1 0x20 ADD SWAP1 MLOAD PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x4F8 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP JUMPDEST PUSH1 0x3 SIGNEXTEND SWAP3 POP POP POP SWAP5 SWAP4 POP POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x60 PUSH2 0x167 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH4 0x99794E8 PUSH1 0xE0 SHL DUP7 DUP7 PUSH1 0x40 MLOAD PUSH1 0x24 ADD DUP1 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP3 POP POP POP PUSH1 0x40 MLOAD PUSH1 0x20 DUP2 DUP4 SUB SUB DUP2 MSTORE SWAP1 PUSH1 0x40 MSTORE SWAP1 PUSH28 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF NOT AND PUSH1 0x20 DUP3 ADD DUP1 MLOAD PUSH28 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP4 DUP2 DUP4 AND OR DUP4 MSTORE POP POP POP POP PUSH1 0x40 MLOAD DUP1 DUP3 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 JUMPDEST PUSH1 0x20 DUP4 LT PUSH2 0x614 JUMPI DUP1 MLOAD DUP3 MSTORE PUSH1 0x20 DUP3 ADD SWAP2 POP PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH1 0x20 DUP4 SUB SWAP3 POP PUSH2 0x5F1 JUMP JUMPDEST PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB DUP1 NOT DUP3 MLOAD AND DUP2 DUP5 MLOAD AND DUP1 DUP3 OR DUP6 MSTORE POP POP POP POP POP POP SWAP1 POP ADD SWAP2 POP POP PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP7 GAS CALL SWAP2 POP POP RETURNDATASIZE DUP1 PUSH1 0x0 DUP2 EQ PUSH2 0x676 JUMPI PUSH1 0x40 MLOAD SWAP2 POP PUSH1 0x1F NOT PUSH1 0x3F RETURNDATASIZE ADD AND DUP3 ADD PUSH1 0x40 MSTORE RETURNDATASIZE DUP3 MSTORE RETURNDATASIZE PUSH1 0x0 PUSH1 0x20 DUP5 ADD RETURNDATACOPY PUSH2 0x67B JUMP JUMPDEST PUSH1 0x60 SWAP2 POP JUMPDEST POP SWAP2 POP SWAP2 POP DUP2 PUSH2 0x68C JUMPI PUSH1 0x15 PUSH2 0x6B3 JUMP JUMPDEST DUP1 DUP1 PUSH1 0x20 ADD SWAP1 MLOAD PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x6A1 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP JUMPDEST PUSH1 0x3 SIGNEXTEND SWAP3 POP POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x60 PUSH2 0x167 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH4 0x49146BDE PUSH1 0xE0 SHL DUP7 DUP7 PUSH1 0x40 MLOAD PUSH1 0x24 ADD DUP1 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP3 POP POP POP PUSH1 0x40 MLOAD PUSH1 0x20 DUP2 DUP4 SUB SUB DUP2 MSTORE SWAP1 PUSH1 0x40 MSTORE SWAP1 PUSH28 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF NOT AND PUSH1 0x20 DUP3 ADD DUP1 MLOAD PUSH28 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP4 DUP2 DUP4 AND OR DUP4 MSTORE POP POP POP POP PUSH1 0x40 MLOAD DUP1 DUP3 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 JUMPDEST PUSH1 0x20 DUP4 LT PUSH2 0x7BB JUMPI DUP1 MLOAD DUP3 MSTORE PUSH1 0x20 DUP3 ADD SWAP2 POP PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH1 0x20 DUP4 SUB SWAP3 POP PUSH2 0x798 JUMP JUMPDEST PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB DUP1 NOT DUP3 MLOAD AND DUP2 DUP5 MLOAD AND DUP1 DUP3 OR DUP6 MSTORE POP POP POP POP POP POP SWAP1 POP ADD SWAP2 POP POP PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP7 GAS CALL SWAP2 POP POP RETURNDATASIZE DUP1 PUSH1 0x0 DUP2 EQ PUSH2 0x81D JUMPI PUSH1 0x40 MLOAD SWAP2 POP PUSH1 0x1F NOT PUSH1 0x3F RETURNDATASIZE ADD AND DUP3 ADD PUSH1 0x40 MSTORE RETURNDATASIZE DUP3 MSTORE RETURNDATASIZE PUSH1 0x0 PUSH1 0x20 DUP5 ADD RETURNDATACOPY PUSH2 0x822 JUMP JUMPDEST PUSH1 0x60 SWAP2 POP JUMPDEST POP SWAP2 POP SWAP2 POP DUP2 PUSH2 0x833 JUMPI PUSH1 0x15 PUSH2 0x85A JUMP JUMPDEST DUP1 DUP1 PUSH1 0x20 ADD SWAP1 MLOAD PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x848 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP JUMPDEST PUSH1 0x3 SIGNEXTEND SWAP3 POP POP POP SWAP3 SWAP2 POP POP JUMP INVALID LOG2 PUSH5 0x6970667358 0x22 SLT KECCAK256 PUSH9 0xBA1095E27DFAF338E8 0xEE SWAP14 MULMOD EQ RETURN 0x28 INVALID PUSH11 0x23627CE5B8245B5FD09275 0xBA PUSH23 0xD964736F6C634300060C00330000000000000000000000 ",
      "sourceMap": "138:923:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;451:334;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;791:268;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;180:265;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;451:334;575:12;590:82;623:7;632:13;647:11;660;590:32;:82::i;:::-;575:97;;2733:2:1;687:39:0;;:8;:39;683:96;;742:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;683:96;451:334;;;;;:::o;791:268::-;873:12;888:56;923:6;931:12;888:34;:56::i;:::-;873:71;;2733:2:1;959:39:0;;:8;:39;955:98;;1014:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;955:98;791:268;;;:::o;180:265::-;261:12;276:55;310:6;318:12;276:33;:55::i;:::-;261:70;;2733:2:1;346:39:0;;:8;:39;342:97;;401:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;342:97;180:265;;;:::o;10522:429:2:-;10634:16;10667:12;10681:19;291:5;10704:22;;10763:42;;;10819:5;10826:6;10834:8;10844:6;10740:111;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10704:148;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10666:186;;;;10877:7;:67;;2587:2:1;10877:67:2;;;10898:6;10887:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10877:67;10862:82;;;;10522:429;;;;;;;;:::o;8041:373::-;8116:16;8145:12;8159:19;291:5;8182:22;;8241:44;;;8299:7;8308:5;8218:96;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8182:133;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8144:171;;;;8340:7;:67;;2587:2:1;8340:67:2;;;8361:6;8350:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8340:67;8325:82;;;;8041:373;;;;;;:::o;5734:371::-;5808:16;5837:12;5851:19;291:5;5874:22;;5933:43;;;5990:7;5999:5;5910:95;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5874:132;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5836:170;;;;6031:7;:67;;2587:2:1;6031:67:2;;;6052:6;6041:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6031:67;6016:82;;;;5734:371;;;;;;:::o"
    },
    "gasEstimates": {
      "creation": {
        "codeDepositCost": "441000",
        "executionCost": "474",
        "totalCost": "441474"
      },
      "external": {
        "tokenAssociate(address,address)": "infinite",
        "tokenDissociate(address,address)": "infinite",
        "tokenTransfer(address,address,address,int64)": "infinite"
      }
    },
    "methodIdentifiers": {
      "tokenAssociate(address,address)": "7f6314d0",
      "tokenDissociate(address,address)": "4753b51b",
      "tokenTransfer(address,address,address,int64)": "3a04033c"
    }
  },
  "abi": [
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "sender",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "tokenAddress",
          "type": "address"
        }
      ],
      "name": "tokenAssociate",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "sender",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "tokenAddress",
          "type": "address"
        }
      ],
      "name": "tokenDissociate",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "tokenId",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "fromAccountId",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "toAccountId",
          "type": "address"
        },
        {
          "internalType": "int64",
          "name": "tokenAmount",
          "type": "int64"
        }
      ],
      "name": "tokenTransfer",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    }
  ]
}

2. Store the Smart Contract Bytecode on Hedera

Create a file using the FileCreateTransaction() API to store the hex-encoded byte code of the "HTS" contract. Once the file is created, you can obtain the file ID from the receipt of the transaction.

Note: The bytecode is required to be hex-encoded. It should not be the actual data the hex represents.

//Import the HTS.json file from the resources folder
ClassLoader cl = HTS.class.getClassLoader();

Gson gson = new Gson();
JsonObject jsonObject;

//Get the json file
InputStream jsonStream = cl.getResourceAsStream("HTS.json");
jsonObject = gson.fromJson(new InputStreamReader(jsonStream, StandardCharsets.UTF_8), JsonObject.class);


//Store the "object" field from the HTS.json file as hex-encoded bytecode
String object = jsonObject.getAsJsonObject("data").getAsJsonObject("bytecode").get("object").getAsString();
byte[] bytecode = object.getBytes(StandardCharsets.UTF_8);

//Create a file on Hedera and store the hex-encoded bytecode
FileCreateTransaction fileCreateTx = new FileCreateTransaction()
        .setKeys(privateKeyTest)
        .setContents(bytecode);

//Submit the file to the Hedera test network
TransactionResponse submitTx = fileCreateTx.execute(client);

//Get the receipt of the file create transaction
TransactionReceipt fileReceipt = submitTx.getReceipt(client);

//Get the file ID
FileId newFileId = fileReceipt.fileId;

//Log the file ID
System.out.println("The smart contract byte code file ID is " + newFileId);

//v2.6.0 Hedera Java SDK
//Get the contract bytecode
const bytecode = htsContract.data.bytecode.object;

//Create a file on Hedera and store the hex-encoded bytecode
const fileCreateTx = new FileCreateTransaction()
    .setContents(bytecode);

//Submit the file to the Hedera test network signing with the transaction fee payer key specified with the client
const submitTx = await fileCreateTx.execute(client);

//Get the receipt of the file create transaction
const fileReceipt = await submitTx.getReceipt(client);

//Get the file ID from the receipt
const bytecodeFileId = fileReceipt.fileId;

//Log the file ID
console.log("The smart contract bytecode file ID is " +bytecodeFileId)
//Get the HTS contract bytecode
rawSmartContract, err := ioutil.ReadFile("./hts.json")
if err != nil {
	println(err.Error(), ": error reading hts.json")
	return
}

var contract contract = contract{}

err = json.Unmarshal([]byte(rawSmartContract), &contract)
if err != nil {
	println(err.Error(), ": error unmarshaling the json file")
	return
}

smartContractByteCode := []byte(contract.Object)

// Upload a file containing the byte code
fileCreateTx, err := hedera.NewFileCreateTransaction().
	SetContents([]byte(smartContractByteCode)).
	Execute(client)

if err != nil {
	println(err.Error(), ": error creating file")
	return
}

//Get the receipt of the transaction
fileTxReceipt, err := fileCreateTx.GetReceipt(client)
if err != nil {
	println(err.Error(), ": error getting file create transaction receipt")
	return
}

//Get the bytecode file ID
byteCodeFileID := *fileTxReceipt.FileID

fmt.Printf("The contract bytecode file ID: %v\n", byteCodeFileID)

3. Deploy a Hedera Smart Contract

Note: You will need to set the gas value high enough to deploy the contract. If you don't have enough gas, you will receive an INSUFFICIENT_GAS response. If you set the value too high you will be refunded a maximum of 20% of the amount that was set for the transaction.

//Deploy the contract
ContractCreateTransaction contractTx = new ContractCreateTransaction()
        //The contract bytecode file
        .setBytecodeFileId(newFileId)
        //The max gas to reserve for this transaction
        .setGas(2_000_000);

//Submit the transaction to the Hedera test network
TransactionResponse contractResponse = contractTx.execute(client);

//Get the receipt of the file create transaction
TransactionReceipt contractReceipt = contractResponse.getReceipt(client);

//Get the smart contract ID
ContractId newContractId = contractReceipt.contractId;

//Log the smart contract ID
System.out.println("The smart contract ID is " + newContractId);

//v2.6.0 Hedera Java SDK
//Deploy the contract instance
const contractTx = await new ContractCreateTransaction()
    //The bytecode file ID
    .setBytecodeFileId(bytecodeFileId)
    //The max gas to reserve
    .setGas(2000000);

//Submit the transaction to the Hedera test network
const contractResponse = await contractTx.execute(client);

//Get the receipt of the file create transaction
const contractReceipt = await contractResponse.getReceipt(client);

//Get the smart contract ID
const newContractId = contractReceipt.contractId;

//Log the smart contract ID
console.log("The smart contract ID is " + newContractId);
// Deploy the contract instance
contractTransactionID, err := hedera.NewContractCreateTransaction().
	//The max gas for the transaction
	SetGas(2000000).
	//The contract bytecode file ID
	SetBytecodeFileID(byteCodeFileID).
	Execute(client)

if err != nil {
	println(err.Error(), ": error creating contract")
	return
}

//Get the contract receipt
contractReceipt, err := contractTransactionID.GetReceipt(client)

//Get the contract contract ID
contractId := *contractReceipt.ContractID

//Log the contract ID
fmt.Printf("The contract ID %v\n", contractId)

4. Call the tokenAssociate Contract Function

The tokenAssociate function in the contract was previously used to associate tokens created with the Hedera Token Service (HTS). However, due to a change in the security model, it is no longer possible to associate HTS tokens using this function. Instead, you should use the Hedera SDK to perform token associations. You will pass the token ID and account ID to the function. The parameters must be provided in the order expected by the function to execute successfully.

//Associate the token to an account using the HTS contract
TokenAssociateTransaction transaction = new TokenAssociateTransaction()
        .setAccountId(accountIdTest)
        .setTokenId(Collections.singletonList(tokenId))
        .freezeWith(client);

//Sign with the account key to associate and submit to the Hedera network
TransactionResponse associateTokenResponse = transaction.sign(privateKeyTest).execute(client);

System.out.println("The transaction status: " +associateTokenResponse.getReceipt(client).status);
//Associate the token to an account using the SDK
const transaction = new TokenAssociateTransaction()
  .setAccountId(accountIdTest)
  .setTokenIds([tokenId])
  .freezeWith(client);

//Sign the transaction with the client
const signTx = await transaction.sign(accountKeyTest);

//Submit the transaction
const submitAssociateTx = await signTx.execute(client);

//Get the receipt
const txReceipt = await submitAssociateTx.getReceipt(client);

//Get transaction status
const txStatus = txReceipt.status;

console.log("The associate transaction was " + txStatus.toString());
//Associate an account with a token
associateTx, err := hedera.NewTokenAssociateTransaction().
    SetAccountID(accountIdTest).
    SetTokenIDs(tokenId).
    FreezeWith(client)

if err != nil {
  panic(err)
}

//Sign with the private key of the account that is being associated to a token, submit the transaction to a Hedera network
associateTxResponse, err := associateTx.Sign(privateKeyTest).Execute(client)

if err != nil {
  panic(err)
}

//Get the receipt
associateTxReceipt, err := associateTxResponse.GetReceipt(client)

if err != nil {
  panic(err)
}

//Get transaction status
txStatus := associateTxReceipt.Status

fmt.Printf("The associate transaction status %v\n", txStatus)

5. Call the approveTokenAllowance Function

Using the approveTokenAllowance function is a crucial step before initiating a transfer with a smart contract on Hedera. This function grants the necessary permissions from the token owner to authorize the transfer. It serves as a stringent access control measure, ensuring that only approved contracts or accounts can spend the designated tokens. You will pass the owner which is the account that owns the fungible tokens and grants the allowance to the spender, the spender who is the account authorized by the owner to spend fungible tokens from the owner's account. The spender covers the transaction fees for token transfers. And the amount which is the number of tokens the spender is authorized to spend from the owner's account.

// Convert the contract ID to an account ID
AccountId contractIdAsAccountId = AccountId.fromString(newContractId.toString());

//Approve the token allowance
AccountAllowanceApproveTransaction transaction = new AccountAllowanceApproveTransaction()
    .approveHbarAllowance(treasuryAccountId, newContractId, Hbar.from(5));

//Sign the transaction with the owner account key and the transaction fee payer key (client)  
TransactionResponse txResponse = transaction.freezeWith(client).sign(treasuryKey).execute(client);

//Request the receipt of the transaction
TransactionReceipt receipt = txResponse.getReceipt(client);

//Get the transaction consensus status
Status transactionStatus = receipt.status;

System.out.println("The transaction consensus status for the allowance function is " +transactionStatus);
//Approve the token allowance
const transactionAllowance = new AccountAllowanceApproveTransaction()
  .approveTokenAllowance(tokenId, treasuryAccountId, newContractId, 5)
  .freezeWith(client);

//Sign the transaction with the owner account key
const signTxAllowance = await transactionAllowance.sign(treasuryKey);

//Sign the transaction with the client operator private key and submit to a Hedera network
const txResponseAllowance = await signTxAllowance.execute(client);

//Request the receipt of the transaction
const receiptAllowance = await txResponseAllowance.getReceipt(client);

//Get the transaction consensus status
const transactionStatusAllowance = receiptAllowance.status;

console.log(
  "The transaction consensus status for the allowance function is " +
    transactionStatusAllowance.toString()
);
//Create the transaction
transaction := hedera.NewAccountAllowanceApproveTransaction().
     ApproveHbarAllowance(ownerAccount, spenderAccountId, Hbar.fromTinybars(500)
        FreezeWith(client)

if err != nil {
    panic(err)
}

//Sign the transaction with the owner account private key   
txResponse, err := transaction.Sign(ownerAccountKey).Execute(client)

//Request the receipt of the transaction
receipt, err := txResponse.GetReceipt(client)
if err != nil {
    panic(err)
}

//Get the transaction consensus status
transactionStatus := receipt.Status

println("The transaction consensus status is ", transactionStatus)

6. Call the tokenTransfer Contract Function

Transfer 100 units of the token to the account that was associated with the token. You will use the ContractExecuteTransaction() API and set the contract function to tokenTransfer. The contract function parameters must be provided in the order of the function expects to receive them.

The transaction must be signed by the account that is sending the tokens. In this case, it is the treasury account.

You can verify the transfer was successful by checking the account token balance!

//Transfer the new token to the account
//Contract function params need to be in the order of the paramters provided in the tokenTransfer contract function
ContractExecuteTransaction tokenTransfer = new ContractExecuteTransaction()
     .setContractId(newContractId)
     .setGas(2_000_000)
     .setFunction("tokenTransfer", new ContractFunctionParameters()
          //The ID of the token
          .addAddress(tokenId.toSolidityAddress())
          //The account to transfer the tokens from
          .addAddress(treasuryAccountId.toSolidityAddress())
          //The account to transfer the tokens to
          .addAddress(accountIdTest.toSolidityAddress())
          //The number of tokens to transfer
         .addInt64(5));

//Sign the token transfer transaction with the treasury account to authorize the transfer and submit
ContractExecuteTransaction signTokenTransfer = tokenTransfer.freezeWith(client).sign(treasuryKey);

//Submit transfer transaction
TransactionResponse submitTransfer = signTokenTransfer.execute(client);

//Get transaction status
Status txStatus = submitTransfer.getReceipt(client).status;

//Verify your account received the 5 tokens
 AccountBalance newAccountBalance = new AccountBalanceQuery()
      .setAccountId(accountIdTest)
      .execute(client);

System.out.println("My new account balance is " +newAccountBalance.tokens);
//Transfer the new token to the account
//Contract function params need to be in the order of the paramters provided in the tokenTransfer contract function
const tokenTransfer = new ContractExecuteTransaction()
    .setContractId(newContractId)
    .setGas(2000000)
    .setFunction("tokenTransfer", new ContractFunctionParameters()
         //The ID of the token
         .addAddress(tokenId.toSolidityAddress())
         //The account to transfer the tokens from
         .addAddress(treasuryAccountId.toSolidityAddress())
         //The account to transfer the tokens to
         .addAddress(accountIdTest.toSolidityAddress())
          //The number of tokens to transfer
         .addInt64(5));

//Sign the token transfer transaction with the treasury account to authorize the transfer and submit
const signTokenTransfer = await tokenTransfer.freezeWith(client).sign(treasuryKey);

//Submit transfer transaction
const submitTransfer = await signTokenTransfer.execute(client);

//Get transaction status
const transferTxStatus = await (await submitTransfer.getReceipt(client)).status;

//Get the transaction status
console.log("The transfer transaction status " +transferTxStatus.toString());

//Verify the account received the 5 tokens
const newAccountBalance = new AccountBalanceQuery()
       .setAccountId(accountIdTest)
       .execute(client);
       
console.log("My new account balance is " +(await newAccountBalance).tokens.toString());
//Transfer the token
transferTx := hedera.NewContractExecuteTransaction().
	//The contract ID
	SetContractID(contractId).
	//The max gas
	SetGas(2000000).
	//The contract function to call and parameters
	SetFunction("tokenTransfer", contractParamsAmount)

//Sign with treasury key to authorize the transfer from the treasury account
signTx, err := transferTx.Sign(treasuryKey).Execute(client)

if err != nil {
	println(err.Error(), ": error executing contract")
	return
}
//Get the receipt
transferTxReceipt, err := signTx.GetReceipt(client)

if err != nil {
	println(err.Error(), ": error getting receipt")
	return
}

//Get transaction status
transferTxStatus := transferTxReceipt.Status

fmt.Printf("The transfer transaction status %v\n", transferTxStatus)

//Verify the transfer by checking the balance
transferAccountBalance, err := hedera.NewAccountBalanceQuery().
	SetAccountID(accountIdTest).
	Execute(client)

if err != nil {
	println(err.Error(), ": error getting balance")
	return
}

//Log the account token balance
fmt.Printf("The account token balance %v\n", transferAccountBalance.Tokens)
  • Associated an HTS token by using the SDK

  • Approved the token allowance so that the contract can transfer tokens

  • Transferred tokens using the deployed contract


Code Check ✅

Java
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.hedera.hashgraph.sdk.*;

import io.github.cdimascio.dotenv.Dotenv;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeoutException;


public class HTS {

    public static void main(String[] args) throws TimeoutException, PrecheckStatusException, ReceiptStatusException, InterruptedException, IOException {

        AccountId accountIdTest = AccountId.fromString(Dotenv.load().get("MY_ACCOUNT_ID"));
        PrivateKey privateKeyTest = PrivateKey.fromString(Dotenv.load().get(MY_PRIVATE_KEY"));

        Client client = Client.forTestnet();
        client.setOperator(accountIdTest, privateKeyTest);

        //Import the HTS.json file from the resources folder
        ClassLoader cl = HTS.class.getClassLoader();

        Gson gson = new Gson();
        JsonObject jsonObject;

        //Get the json file
        InputStream jsonStream = cl.getResourceAsStream("HTS.json");
        jsonObject = gson.fromJson(new InputStreamReader(jsonStream, StandardCharsets.UTF_8), JsonObject.class);


        //Store the "object" field from the HTS.json file as hex-encoded bytecode
        String object = jsonObject.getAsJsonObject("data").getAsJsonObject("bytecode").get("object").getAsString();
        byte[] bytecode = object.getBytes(StandardCharsets.UTF_8);

        //Create a treasury Key
        PrivateKey treasuryKey = PrivateKey.generateECDSA();
        PublicKey treasuryPublicKey = treasuryKey.getPublicKey();

        //Create a treasury account
        AccountCreateTransaction treasuryAccount = new AccountCreateTransaction()
                .setKey(treasuryPublicKey)
                //Do NOT set an alias if you need to update/rotate keys in the future
                .setAlias(treasuryPublicKey.toEvmAddress())
                .setInitialBalance(new Hbar(10))
                .setAccountMemo("treasury account");

        //Submit the account create transaction
        TransactionResponse submitAccountCreateTx = treasuryAccount.execute(client);

        //Get the receipt of the transaction
        TransactionReceipt newAccountReceipt = submitAccountCreateTx.getReceipt(client);

        //Get the treasury account ID
        AccountId treasuryAccountId = newAccountReceipt.accountId;
        System.out.println("The new account ID is " +treasuryAccountId);

        //Create a token to interact with
        TokenCreateTransaction createToken = new TokenCreateTransaction()
                .setTokenName("HSCS demo")
                .setTokenSymbol("H")
                .setTokenType(TokenType.FUNGIBLE_COMMON)
                .setTreasuryAccountId(treasuryAccountId)
                .setInitialSupply(500);

        //Submit the token create transaction
        TransactionResponse submitTokenTx = createToken.freezeWith(client).sign(treasuryKey).execute(client);

        //Get the token ID
        TokenId tokenId = submitTokenTx.getReceipt(client).tokenId;
        System.out.println("The new token ID is " +tokenId);


        //Create a file on Hedera and store the hex-encoded bytecode
        FileCreateTransaction fileCreateTx = new FileCreateTransaction()
                .setKeys(privateKeyTest)
                .setContents(bytecode);

        //Submit the file to the Hedera test network
        TransactionResponse submitTx = fileCreateTx.execute(client);

        //Get the receipt of the file create transaction
        TransactionReceipt fileReceipt = submitTx.getReceipt(client);

        //Get the file ID
        FileId newFileId = fileReceipt.fileId;

        //Log the file ID
        System.out.println("The smart contract byte code file ID is " + newFileId);


        //Deploy the contract
        ContractCreateTransaction contractTx = new ContractCreateTransaction()
                //The contract bytecode file
                .setBytecodeFileId(newFileId)
                //The max gas to reserve for this transaction
                .setGas(2_000_000);

        //Submit the transaction to the Hedera test network
        TransactionResponse contractResponse = contractTx.execute(client);

        //Get the receipt of the file create transaction
        TransactionReceipt contractReceipt = contractResponse.getReceipt(client);

        //Get the smart contract ID
        ContractId newContractId = contractReceipt.contractId;

        //Log the smart contract ID
        System.out.println("The smart contract ID is " + newContractId);

        //Associate the token to an account using the SDK
        TokenAssociateTransaction transaction = new TokenAssociateTransaction()
                .setAccountId(accountIdTest)
                .setTokenId(Collections.singletonList(tokenId))
                .freezeWith(client)


        //Sign with the account key to associate and submit to the Hedera network
        TransactionResponse associateTokenResponse = transaction.sign(privateKeyTest).execute(client);

        System.out.println("The transaction status: " +associateTokenResponse.getReceipt(client).status);

        // Convert the contract ID to an account ID
        AccountId contractIdAsAccountId = AccountId.fromString(newContractId.toString());
        
        //Approve the token allowance so that the contract can transfer tokens from the treasury account
        AccountAllowanceApproveTransaction transaction = new AccountAllowanceApproveTransaction()
                .approveTokenAllowance(tokenId, treasuryAccountId, contractIdAsAccountId, 10);

        //Sign the transaction with the owner account key and the transaction fee payer key (client)  
        TransactionResponse txResponse = transaction.freezeWith(client).sign(treasuryKey).execute(client);

        //Request the receipt of the transaction
        TransactionReceipt receipt = txResponse.getReceipt(client);

        //Get the transaction consensus status
        Status transactionStatus = receipt.status;

        System.out.println("The transaction consensus status is " +transactionStatus);

        //Transfer the new token to the account
        //Contract function params need to be in the order of the paramters provided in the tokenTransfer contract function
        ContractExecuteTransaction tokenTransfer = new ContractExecuteTransaction()
                .setContractId(newContractId)
                .setGas(2_000_000)
                .setFunction("tokenTransfer", new ContractFunctionParameters()
                        //The ID of the token
                        .addAddress(tokenId.toSolidityAddress())
                        //The account to transfer the tokens from
                        .addAddress(treasuryAccountId.toSolidityAddress())
                        //The account to transfer the tokens to
                        .addAddress(accountIdTest.toSolidityAddress())
                        //The number of tokens to transfer
                        .addInt64(5);

        //Sign the token transfer transaction with the treasury account to authorize the transfer and submit
        ContractExecuteTransaction signTokenTransfer = tokenTransfer.freezeWith(client).sign(treasuryKey);

        //Submit transfer transaction
        TransactionResponse submitTransfer = signTokenTransfer.execute(client);

        //Get transaction status
        Status txStatus = submitTransfer.getReceipt(client).status;

        //Get the transaction status
        System.out.println("The transfer transaction status " +txStatus);

        //Verify your account received the 5 tokens
        AccountBalance newAccountBalance = new AccountBalanceQuery()
                .setAccountId(accountIdTest)
                .execute(client);

        System.out.println("My new account balance is " +newAccountBalance.tokens);
    }
}
JavaScript
require("dotenv").config();

const {
  Hbar,
  Client,
  AccountId,
  TokenType,
  PrivateKey,
  AccountBalanceQuery,
  FileCreateTransaction,
  TokenCreateTransaction,
  ContractCreateTransaction,
  ContractExecuteTransaction,
  ContractFunctionParameters,
  AccountCreateTransaction,
  AccountAllowanceApproveTransaction,
  TokenAssociateTransaction,
} = require("@hashgraph/sdk");

// Import the compiled contract
const htsContract = require("./HTS.json");

async function htsContractFunction() {
  //Grab your Hedera testnet account ID and private key from your .env file
  const accountIdTest = AccountId.fromString(process.env.MY_ACCOUNT_ID);
  const accountKeyTest = PrivateKey.fromStringECDSA(
    process.env.MY_PRIVATE_KEY
  );

  // If we weren't able to grab it, we should throw a new error
  if (accountIdTest == null || accountKeyTest == null) {
    throw new Error(
      "Environment variables myAccountId and myPrivateKey must be present"
    );
  }

  const client = Client.forTestnet();
  client.setOperator(accountIdTest, accountKeyTest);

  //Get the contract bytecode
  const bytecode = htsContract.data.bytecode.object;

  //Treasury Key
  const treasuryKey = PrivateKey.generateECDSA();
  const treasuryPublicKey = treasuryKey.publicKey;

  //Create token treasury account
  const treasuryAccount = new AccountCreateTransaction()
    .setKey(treasuryKey)
    //Do NOT set an alias if you need to update/rotate keys in the future
    .setAlias(treasuryPublicKey.toEvmAddress())
    .setInitialBalance(new Hbar(5))
    .setAccountMemo("treasury account");

  //Submit the transaction to a Hedera network
  const submitAccountCreateTx = await treasuryAccount.execute(client);

  //Get the receipt of the transaction
  const newAccountReceipt = await submitAccountCreateTx.getReceipt(client);

  //Get the account ID from the receipt
  const treasuryAccountId = newAccountReceipt.accountId;

  console.log("The new account ID is " + treasuryAccountId);

  //Create a token to interact with
  const createToken = new TokenCreateTransaction()
    .setTokenName("HTS demo")
    .setTokenSymbol("H")
    .setTokenType(TokenType.FungibleCommon)
    .setTreasuryAccountId(treasuryAccountId)
    .setInitialSupply(500);

  //Sign with the treasury key
  const signTokenTx = await createToken.freezeWith(client).sign(treasuryKey);

  //Submit the transaction to a Hedera network
  const submitTokenTx = await signTokenTx.execute(client);

  //Get the token ID from the receipt
  const tokenId = await (await submitTokenTx.getReceipt(client)).tokenId;

  //Log the token ID
  console.log("The new token ID is " + tokenId);

  //Create a file on Hedera and store the hex-encoded bytecode
  const fileCreateTx = new FileCreateTransaction().setContents(bytecode);

  //Submit the file to the Hedera test network signing with the transaction fee payer key specified with the client
  const submitTx = await fileCreateTx.execute(client);

  //Get the receipt of the file create transaction
  const fileReceipt = await submitTx.getReceipt(client);

  //Get the file ID from the receipt
  const bytecodeFileId = fileReceipt.fileId;

  //Log the file ID
  console.log("The smart contract byte code file ID is " + bytecodeFileId);

  //Deploy the contract instance
  const contractTx = await new ContractCreateTransaction()
    //The bytecode file ID
    .setBytecodeFileId(bytecodeFileId)
    //The max gas to reserve
    .setGas(2000000);

  //Submit the transaction to the Hedera test network
  const contractResponse = await contractTx.execute(client);

  //Get the receipt of the file create transaction
  const contractReceipt = await contractResponse.getReceipt(client);

  //Get the smart contract ID
  const newContractId = contractReceipt.contractId;

  //Log the smart contract ID
  console.log("The smart contract ID is " + newContractId);

  //Associate the token to an account using the SDK
  const transaction = new TokenAssociateTransaction()
    .setAccountId(accountIdTest)
    .setTokenIds([tokenId])
    .freezeWith(client);

  //Sign the transaction with the client
  const signTx = await transaction.sign(accountKeyTest);

  //Submit the transaction
  const submitAssociateTx = await signTx.execute(client);

  //Get the receipt
  const txReceipt = await submitAssociateTx.getReceipt(client);

  //Get transaction status
  const txStatus = txReceipt.status;

  console.log("The associate transaction was " + txStatus.toString());

  //Approve the token allowance
  const transactionAllowance = new AccountAllowanceApproveTransaction()
    .approveTokenAllowance(tokenId, treasuryAccountId, newContractId, 5)
    .freezeWith(client);

  //Sign the transaction with the owner account key
  const signTxAllowance = await transactionAllowance.sign(treasuryKey);

  //Sign the transaction with the client operator private key and submit to a Hedera network
  const txResponseAllowance = await signTxAllowance.execute(client);

  //Request the receipt of the transaction
  const receiptAllowance = await txResponseAllowance.getReceipt(client);

  //Get the transaction consensus status
  const transactionStatusAllowance = receiptAllowance.status;

  console.log(
    "The transaction consensus status for the allowance function is " +
      transactionStatusAllowance.toString()
  );

  //Transfer the new token to the account
  //Contract function params need to be in the order of the parameters provided in the tokenTransfer contract function
  const tokenTransfer = new ContractExecuteTransaction()
    .setContractId(newContractId)
    .setGas(2000000)
    .setFunction(
      "tokenTransfer",
      new ContractFunctionParameters()
        //The ID of the token
        .addAddress(tokenId.toSolidityAddress())
        //The account to transfer the tokens from
        .addAddress(treasuryAccountId.toSolidityAddress())
        //The account to transfer the tokens to
        .addAddress(accountIdTest.toSolidityAddress())
        //The number of tokens to transfer
        .addInt64(5)
    );

  //Sign the token transfer transaction with the treasury account to authorize the transfer and submit
  const signTokenTransfer = await tokenTransfer
    .freezeWith(client)
    .sign(treasuryKey);

  //Submit transfer transaction
  const submitTransfer = await signTokenTransfer.execute(client);

  //Get transaction status
  const transferTxStatus = await (
    await submitTransfer.getReceipt(client)
  ).status;

  //Get the transaction status
  console.log("The transfer transaction status " + transferTxStatus.toString());

  //Verify your account received the 10 tokens
  const newAccountBalance = new AccountBalanceQuery()
    .setAccountId(accountIdTest)
    .execute(client);

  console.log(
    "My new account balance is " + (await newAccountBalance).tokens.toString()
  );
}

void htsContractFunction();
Go
package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"

	"github.com/hashgraph/hedera-sdk-go/v2"
	"github.com/joho/godotenv"
)

type contract struct {
	// ignore the link references since it is empty
	Object    string `json:"object"`
	OpCodes   string `json:"opcodes"`
	SourceMap string `json:"sourceMap"`
}

func main() {

	//Loads the .env file and throws an error if it cannot load the variables from that file corectly
	err := godotenv.Load(".env")
	if err != nil {
		panic(fmt.Errorf("Unable to load enviroment variables from .env file. Error:\n%v\n", err))
	}

	//Grab your testnet account ID and private key from the .env file
	accountIdTest, err := hedera.AccountIDFromString(os.Getenv("MY_ACCOUNT_ID"))
	if err != nil {
		panic(err)
	}

	privateKeyTest, err := hedera.PrivateKeyFromString(os.Getenv("MY_PRIVATE_KEY"))
	if err != nil {
		panic(err)
	}

	//Create your testnet client
	client := hedera.ClientForTestnet()
	client.SetOperator(accountIdTest, privateKeyTest)

	//Treasury Key
	treasuryKey, err := hedera.PrivateKeyGenerateEcdsa()
	treasuryPublicKey := treasuryKey.PublicKey()

	//Create token treasury account
	treasuryAccount := hedera.NewAccountCreateTransaction().
		SetKey(treasuryPublicKey).
    		//Do NOT set an alias if you need to update/rotate keys in the future
    		SetAlias(treasuryPublicKey.ToEvmAddress()).
		SetInitialBalance(hedera.NewHbar(5).
		SetAccountMemo("treasury account")

	//Submit the transaction to a Hedera network
	submitAccountCreateTx, err := treasuryAccount.Execute(client)

	//Get the receipt of the transaction
	newAccountReceipt, err := submitAccountCreateTx.GetReceipt(client)

	//Get the account ID from the receipt
	treasuryAccountId := *newAccountReceipt.AccountID

	fmt.Printf("The treasury account ID: %v\n", treasuryAccountId)

	//Create a token to interact with
	createToken := hedera.NewTokenCreateTransaction().
		SetTokenName("HTS demo").
		SetTokenSymbol("H").
		SetTokenType(hedera.TokenTypeFungibleCommon).
		SetTreasuryAccountID(treasuryAccountId).
		SetInitialSupply(500)

	//Freeze the transaction for signing
	freezeTokenTx, err := createToken.FreezeWith(client)

	//Sign with the treasury key to authorize the transaction
	signTokenTx := freezeTokenTx.Sign(treasuryKey)

	//Submit the transaction
	submitTokenTx, err := signTokenTx.Execute(client)

	//Get the receipt of the transaction
	getTokenReceipt, err := submitTokenTx.GetReceipt(client)

	//Get the token ID
	tokenId := *getTokenReceipt.TokenID

	//Log the token ID
	fmt.Printf("The token ID: %v\n", tokenId)

	//Get the HTS contract bytecode
	rawSmartContract, err := ioutil.ReadFile("./hts.json")
	if err != nil {
		println(err.Error(), ": error reading hts.json")
		return
	}

	var contract contract = contract{}

	err = json.Unmarshal([]byte(rawSmartContract), &contract)
	if err != nil {
		println(err.Error(), ": error unmarshaling the json file")
		return
	}

	smartContractByteCode := []byte(contract.Object)

	// Upload a file containing the byte code
	fileCreateTx, err := hedera.NewFileCreateTransaction().
		SetContents([]byte(smartContractByteCode)).
		Execute(client)

	if err != nil {
		println(err.Error(), ": error creating file")
		return
	}

	//Get the receipt of the transaction
	fileTxReceipt, err := fileCreateTx.GetReceipt(client)
	if err != nil {
		println(err.Error(), ": error getting file create transaction receipt")
		return
	}

	//Get the bytecode file ID
	byteCodeFileID := *fileTxReceipt.FileID

	fmt.Printf("The contract bytecode file ID: %v\n", byteCodeFileID)

	// Deploy the contract instance
	contractTransactionID, err := hedera.NewContractCreateTransaction().
		//The max gas for the transaction
		SetGas(2000000).
		//The contract bytecode file ID
		SetBytecodeFileID(byteCodeFileID).
		Execute(client)

	if err != nil {
		println(err.Error(), ": error creating contract")
		return
	}

	//Get the contract receipt
	contractReceipt, err := contractTransactionID.GetReceipt(client)

	//Get the contract contract ID
	contractId := *contractReceipt.ContractID

	//Log the contract ID
	fmt.Printf("The contract ID %v\n", contractId)

	//Associate an account with a token
	associateTx, err := hedera.NewTokenAssociateTransaction().
    	SetAccountID(accountIdTest).
    	SetTokenIDs(tokenId).
    	FreezeWith(client)

	if err != nil {
	  panic(err)
	}

	//Sign with the private key of the account that is being associated to a token, submit the transaction to a Hedera network
	associateTxResponse, err := associateTx.Sign(privateKeyTest).Execute(client)

	if err != nil {
	  panic(err)
	}

	//Get the receipt
	associateTxReceipt, err := associateTxResponse.GetReceipt(client)

	if err != nil {
	  panic(err)
	}

	//Get transaction status
	txStatus := associateTxReceipt.Status

	fmt.Printf("The associate transaction status %v\n", txStatus)

	//Create the transaction
	transaction := hedera.NewAccountAllowanceApproveTransaction().
     	ApproveHbarAllowance(ownerAccount, spenderAccountId, Hbar.fromTinybars(500))
        	FreezeWith(client)

	if err != nil {
    		panic(err)
	}

	//Sign the transaction with the owner account private key   
	txResponse, err := transaction.Sign(ownerAccountKey).Execute(client)

	//Request the receipt of the transaction
	receipt, err := txResponse.GetReceipt(client)
	if err != nil {
    		panic(err)
	}

	//Get the transaction consensus status
	transactionStatus := receipt.Status

	println("The transaction consensus status is ", transactionStatus)
	
	//Transfer the token
	transferTx := hedera.NewContractExecuteTransaction().
		//The contract ID
		SetContractID(contractId).
		//The max gas
		SetGas(2000000).
		//The contract function to call and parameters
		SetFunction("tokenTransfer", contractParamsAmount)

	//Sign with treasury key to authorize the transfer from the treasury account
	signTx, err := transferTx.Sign(treasuryKey).Execute(client)

	if err != nil {
		println(err.Error(), ": error executing contract")
		return
	}
	//Get the receipt
	transferTxReceipt, err := signTx.GetReceipt(client)

	if err != nil {
		println(err.Error(), ": error getting receipt")
		return
	}

	//Get transaction status
	transferTxStatus := transferTxReceipt.Status

	fmt.Printf("The transfer transaction status %v\n", transferTxStatus)

	//Verify the transfer by checking the balance
	transferAccountBalance, err := hedera.NewAccountBalanceQuery().
		SetAccountID(accountIdTest).
		Execute(client)

	if err != nil {
		println(err.Error(), ": error getting balance")
		return
	}

	//Log the account token balance
	fmt.Printf("The account token balance %v\n", transferAccountBalance.Tokens)

}

Additional Resources

To write a contract using HTS, you will need to add the HTS Solidity support libraries to your project and import them into your contract. Please see the HTS.sol example for reference. The IHederaTokenService.sol will need to be in the same directory as the other two files. An explanation of the functions can be found .

Create the contract and set the file ID to the file that contains the hex-encoded bytecode from the previous step. You will need to set the gas high enough to deploy the contract. The gas should be estimated to be within 25% of the actual gas cost to avoid paying extra gas. You can read more about gas and fees .

Note: Check out our that return information about a contract like contract results and logs!

Congratulations ! You have learned how to deploy a contract using the Hedera Token Service and completed the following:

➡ Have a question? Ask on

➡ Feel free to reach out in !

🎉
HIP-16
Hedera testnet account
here
here
HederaTokenService.sol
HederaResponseCodes.sol
IHederaTokenService.sol
StackOverflow
Discord

Writer: Simi, Sr. Software Manager

Editor: Krystal, Technical Writer

Editor: Lucía, Developer

(Hashgraph Association)

|

|

|

GitHub
LinkedIn
GitHub
Twitter
GitHub
Twitter
smart contract mirror node rest APIs
here