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 Upgrade an ERC-721 Token with OpenZeppelin UUPS Proxies and Hardhat (Part 3)
      • 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 Contract Builder
    • 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
  • Prerequisites
  • Table of Contents
  • Project Setup
  • Project Configuration
  • Project Contents
  • Running the project

Was this helpful?

Edit on GitHub
  1. Tutorials
  2. Smart Contracts

The Power of Native Hedera Tokens as ERC-20 Tokens: A step-by-step guide

PreviousDeploy Smart Contracts on Hedera Using TruffleNextHTS x EVM - Part 1: How to Mint NFTs

Last updated 9 months ago

Was this helpful?

In this tutorial, you’ll learn how to make Hedera native tokens work like Ethereum's ERC-20 tokens using the JSON-RPC instance.


Prerequisites

  • Basic understanding of and .

  • Get a .

  • Have installed.


Table of Contents


Project Setup

Open a terminal window and navigate to your preferred directory where your project will live. Run the following command to clone the repo and install dependencies to your local machine:

git clone https://github.com/Swiss-Digital-Assets-Institute/token-wrapper.git
cd token-wrapper
npm install

The dotenv package is used to manage environment variables in a separate .env file, which is loaded at runtime. This helps protect sensitive information like your private keys and API secrets, but it's still best practice to add .env to your .gitignore to prevent you from pushing your credentials to GitHub.


Project Configuration

In this step, you will update and configure the Hardhat configuration file that defines tasks, stores Hedera account private key information, and Hashio Testnet RPC URL. First, rename the .env.example file to .env. and update the .env files with the following code.

Environment Variables

The .env file defines environment variables used in the project. The MY_ACCOUNT_ID and MY_PRIVATE_KEY variables contains the ECDSA Account ID and DER Encoded Private Key, respectively for the Hedera Testnet account. The HEX_ENCODED_PRIVATE_KEY variable contains the HEX Encoded Private Key.

.env
MY_ACCOUNT_ID =
MY_PRIVATE_KEY = 
HEX_ENCODED_PRIVATE_KEY = 
JSON_RPC_RELAY_URL = https://testnet.hashio.io/api

Project Contents

This directory contains compiled smart contracts used for generating TypeScript bindings with Typechain. We compile these contracts using Hardhat, a versatile Ethereum development tool. You'll find the configuration in hardhat.config.js.

Think of Hardhat as your all-in-one environment for Ethereum development tasks like compiling, deploying, testing, and debugging.

This directory contains the smart contracts that will be compiled and deployed to the Hedera network. This directory contains the smart contracts that will be compiled and deployed to the Hedera network. Let's take a look at the smart contracts in this directory:

  • ERC20.sol - This is the ERC20 token contract.

  • HederaResponseCodes.sol - This is a contract that contains the response codes for the Hedera network.

  • HederaTokenService.sol - This contract provides the transactions to interact with the tokens created on Hedera.

  • IHederaTokenService.sol - This is the interface for the HederaTokenService contract.

  • Vault.sol - This contract, when deployed, manages the functionality of a vault and serves as a testing ground to understand how Hedera native tokens interact with the ERC20 contract.

In this directory, you'll find two main scripts: ERC20.ts and utils.ts. They play a crucial role in our interaction with smart contracts. Here's how it all unfolds:

We kick things off by setting up our environment and defining the essential variables. Using the Hedera SDK, we create a new fungible token, which gives us a unique tokenId.

To streamline our interaction with smart contracts, we utilize the Typechain class to create instances of contractERC20 and contractVault. We provide contractERC20 with the tokenId's solidity address and the Ethereum provider. Similarly, we create an instance for contractVault using the vaultContractAddress (after deployed) and the provider. This approach ensures that both contracts are seamlessly integrated into our development process.

With our environment ready, we dive into interactions with the contracts. We demonstrate a token transfer operation, moving native tokens created on Hedera from one account to another through the ERC20 contract. After that, we check how the balance of the receiving account changes. We do this in two ways: first, by calling a function in the SDK, and second, by using the balanceOf function in the ERC20 contract.

In our second example, we deposit 1000 tokens into the Vault contract and then withdraw them. We keep an eye on how this affects the Vault contract's balance. It's worth noting that in Hedera, you need to associate the recipient account with the token before making transfers. To handle this requirement, we use the associate function from the HederaTokenService contract, which establishes the connection between the Vault contract and the token. Once associated, we can easily deposit and withdraw tokens.

ERC20.ts
console.clear();
import { AccountId, PrivateKey, TokenAssociateTransaction, Client, AccountBalanceQuery } from "@hashgraph/sdk";
import { ethers } from "ethers";
import { createFungibleToken, createAccount, deployContract } from "./utils";

import { ERC20__factory } from '../typechain-types/factories/ERC20__factory';
import { Vault__factory } from '../typechain-types/factories/Vault__factory';

import { config } from "dotenv";

config();

// Provider to connect to the Ethereum network
const provider = new ethers.providers.JsonRpcProvider(process.env.JSON_RPC_RELAY_URL!);

// Wallet to sign the transactions
const wallet = new ethers.Wallet(process.env.HEX_ENCODED_PRIVATE_KEY!, provider);

// Client to interact with the Hedera network
const client = Client.forTestnet();
const operatorPrKey = PrivateKey.fromStringECDSA(process.env.HEX_ENCODED_PRIVATE_KEY!);
const operatorAccountId = AccountId.fromString(process.env.MY_ACCOUNT_ID!);
client.setOperator(operatorAccountId, operatorPrKey);

async function main() {

    // Create a fungible token with the SDK
    const tokenId = await createFungibleToken("TestToken", "TT", operatorAccountId, operatorPrKey.publicKey, client, operatorPrKey);

    // Create an account for Alice with 10 hbar using the SDK
    const aliceKey = PrivateKey.generateED25519();
    const aliceAccountId = await createAccount(client, aliceKey, 10);
    console.log(`- Alice account id created: ${aliceAccountId!.toString()}`);

    // Take the address of the tokenId
    const tokenIdAddress = tokenId!.toSolidityAddress();
    console.log(`- tokenIdAddress`, tokenIdAddress);

    // We connect to the ERC20 contract using typechain
    const account = wallet.connect(provider);
    const accountAddress = account.address;
    console.log(`- accountAddress`, accountAddress);

    const contractERC20 = ERC20__factory.connect(
        tokenIdAddress,
        account
    );

    // We deploy the Vault contract using the SDK and take the address
    const contractVaultId = await deployContract(client, Vault__factory.bytecode, 4000000);
    const contractVaultAddress = contractVaultId!.toSolidityAddress();
    console.log(`- contractVaultId`, contractVaultId!.toString());

    // We connect to the Vault contract using typechain
    const contractVault = Vault__factory.connect(
        contractVaultAddress,
        wallet
    );

    // We set Alice as the operator, now she is the one interacting with the hedera network
    const aliceClient = client.setOperator(aliceAccountId!, aliceKey);

    // We associate the Alice account with the token
    const tokenAssociate = await new TokenAssociateTransaction()
        .setAccountId(aliceAccountId!)
        .setTokenIds([tokenId!])
        .execute(aliceClient);

    const tokenAssociateReceipt = await tokenAssociate.getReceipt(aliceClient);
    console.log(`- tokenAssociateReceipt ${tokenAssociateReceipt.status.toString()}`);

    const aliceAccountAddress = aliceAccountId!.toSolidityAddress();
    // We transfer 10 tokens to Alice using the ERC20 contract
    const transfer = await contractERC20.transfer(aliceAccountAddress, 10, { gasLimit: 1000000 })
    const transferReceiptWait = await transfer.wait();
    console.log(`- Transfer`, transferReceiptWait);

    // We check the balance tokenId from Alice using the SDK
    const balanceAliceNativeToken = new AccountBalanceQuery()
        .setAccountId(aliceAccountId!)

    const transactionQuery = await balanceAliceNativeToken.execute(client);
    const balanceTokenSDK = transactionQuery.tokens!.get(tokenId!);
    console.log("- Balance from Alice using the SDK", balanceTokenSDK.toString());

    // We check the balance tokenId from Alice using the ERC20 contract
    const balanceAliceERC20 = await contractERC20.balanceOf(aliceAccountAddress);
    console.log("- Balance from Alice using the ERC20", parseInt(balanceAliceERC20.toString()));

    // We associate the Vault contract with the token so we can transfer tokens to it
    const associate = await contractVault.associateFungibleToken(tokenIdAddress, { gasLimit: 1000000 })
    const associateReceipt = await associate.wait();
    console.log(`- Associate`, associateReceipt);

    // We deposit 1000 tokens to the Vault contract
    const deposit = await contractERC20.transfer(contractVaultAddress, 1000, { gasLimit: 1000000 })
    const depositReceipt = await deposit.wait();
    console.log(`- Deposit tokens to the Vault contract`, depositReceipt);

    // We check the balance of the Vault contract after the deposit
    let balanceVaultERC20 = await contractERC20.balanceOf(contractVaultAddress);
    console.log(`- Balance of the Vault contract before the withdraw`, parseInt(balanceVaultERC20.toString()));

    // We withdraw 100 tokens from the Vault contract
    const withdraw = await contractVault.withdraw(tokenIdAddress, { gasLimit: 1000000 })
    const withdrawReceipt = await withdraw.wait();
    console.log(`- Withdraw tokens from the Vault contract`, withdrawReceipt);

    // We check again the balance of the Vault contract after the withdraw to see if it has changed
    balanceVaultERC20 = await contractERC20.balanceOf(contractVaultAddress);
    console.log(`- Balance of the Vault contract after the withdraw`, parseInt(balanceVaultERC20.toString()));

}

main();

This directory contains the typescript bindings generated by typechain. These bindings are used to interact with the smart contracts.


Running the project

Now that you have your project set up and configured, we can run it.

To do so, run the following command:

npm run compile
ts-node scripts/ERC20.ts

The first command compiles the smart contracts and generates the typescript bindings. The second command runs the ERC20 script.

Note: At the top of the explorer page, remember to switch the network to TESTNET before you search for the transaction.

console check ✅
- The token ID is: 0.0.2576296
- Alice account id created: 0.0.2576297
- tokenIdAddress 0000000000000000000000000000000000274fa8
- accountAddress 0x398520c72090d7aaBe37e2c49ab1cAe8e662AEa0
- contractVaultId 0.0.2576303
- tokenAssociateReceipt SUCCESS
- Transfer {
	to: '0x0000000000000000000000000000000000274Fa8',
	from: '0x398520c72090d7aaBe37e2c49ab1cAe8e662AEa0',
	contractAddress: '0x0000000000000000000000000000000000274Fa8',
	transactionIndex: 1,
	gasUsed: BigNumber { _hex: '0x0c3500', _isBigNumber: true },
	logsBloom: '0x00000000000000040000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000080000000000000000000000008000000000000000000000000000000000000000000000000000020000000000000000000100000000000000000000010000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000080000000000000000',
	blockHash: '0xe9714ef3227d3c809981ce42eb81d9c0fcd8e8082f4931628ab1d296b3e0d5bd',
	transactionHash: '0x5b730724e757a45b21f833a2f8bf8ae510cb7fa61d5defcde68f4432dfcf9940',
	logs: [
	{
		transactionIndex: 1,
		blockNumber: 2490825,
		transactionHash: '0x5b730724e757a45b21f833a2f8bf8ae510cb7fa61d5defcde68f4432dfcf9940',
		address: '0x0000000000000000000000000000000000274Fa8',
		topics: [Array],
		data: '0x000000000000000000000000000000000000000000000000000000000000000a',
		logIndex: 0,
		blockHash: '0xe9714ef3227d3c809981ce42eb81d9c0fcd8e8082f4931628ab1d296b3e0d5bd'
	}
	],
	blockNumber: 2490825,
	confirmations: 1,
	cumulativeGasUsed: BigNumber { _hex: '0x0c3500', _isBigNumber: true },
	effectiveGasPrice: BigNumber { _hex: '0x03179fcad000', _isBigNumber: true },
	status: 1,
	type: 2,
	byzantium: true,
	events: [
	{
		transactionIndex: 1,
		blockNumber: 2490825,
		transactionHash: '0x5b730724e757a45b21f833a2f8bf8ae510cb7fa61d5defcde68f4432dfcf9940',
		address: '0x0000000000000000000000000000000000274Fa8',
		topics: [Array],
		data: '0x000000000000000000000000000000000000000000000000000000000000000a',
		logIndex: 0,
		blockHash: '0xe9714ef3227d3c809981ce42eb81d9c0fcd8e8082f4931628ab1d296b3e0d5bd',
		args: [Array],
		decode: [Function (anonymous)],
		event: 'Transfer',
		eventSignature: 'Transfer(address,address,uint256)',
		removeListener: [Function (anonymous)],
		getBlock: [Function (anonymous)],
		getTransaction: [Function (anonymous)],
		getTransactionReceipt: [Function (anonymous)]
	}
	]
}
- Balance from Alice using the SDK 10
- Balance from Alice using the ERC20 10
- Associate {
	to: '0x0000000000000000000000000000000000274faF',
	from: '0x398520c72090d7aaBe37e2c49ab1cAe8e662AEa0',
	contractAddress: '0x0000000000000000000000000000000000274faF',
	transactionIndex: 0,
	gasUsed: BigNumber { _hex: '0x0c3500', _isBigNumber: true },
	logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
	blockHash: '0x2a7393098da0e5f82da2230dfecb124b5be86d52bea2bb45924658c8c8a83ad3',
	transactionHash: '0x513f8ecbd25c8326c52c161e47d56f9f40d59e179ca670ec49bf0d316561d863',
	logs: [],
	blockNumber: 2490828,
	confirmations: 1,
	cumulativeGasUsed: BigNumber { _hex: '0x0c3500', _isBigNumber: true },
	effectiveGasPrice: BigNumber { _hex: '0x03179fcad000', _isBigNumber: true },
	status: 1,
	type: 2,
	byzantium: true,
	events: []
}
- Deposit tokens to the Vault contract {
	to: '0x0000000000000000000000000000000000274Fa8',
	from: '0x398520c72090d7aaBe37e2c49ab1cAe8e662AEa0',
	contractAddress: '0x0000000000000000000000000000000000274Fa8',
	transactionIndex: 0,
	gasUsed: BigNumber { _hex: '0x0c3500', _isBigNumber: true },
	logsBloom: '0x00800000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000008000000000000000000000000000000000000000000000004000000000000000000000000100000000000000000000010000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000080000000000000000',
	blockHash: '0xb8553decd07d595c77eaa17c019e0f506ab0632da614971b006a6b1353d5e57a',
	transactionHash: '0x3b312bb272236d00e750294d81d3c7441208b84c9f6f97b2a25757d19c0b444f',
	logs: [
	{
		transactionIndex: 0,
		blockNumber: 2490831,
		transactionHash: '0x3b312bb272236d00e750294d81d3c7441208b84c9f6f97b2a25757d19c0b444f',
		address: '0x0000000000000000000000000000000000274Fa8',
		topics: [Array],
		data: '0x00000000000000000000000000000000000000000000000000000000000003e8',
		logIndex: 0,
		blockHash: '0xb8553decd07d595c77eaa17c019e0f506ab0632da614971b006a6b1353d5e57a'
	}
	],
	blockNumber: 2490831,
	confirmations: 2,
	cumulativeGasUsed: BigNumber { _hex: '0x0c3500', _isBigNumber: true },
	effectiveGasPrice: BigNumber { _hex: '0x03179fcad000', _isBigNumber: true },
	status: 1,
	type: 2,
	byzantium: true,
	events: [
	{
		transactionIndex: 0,
		blockNumber: 2490831,
		transactionHash: '0x3b312bb272236d00e750294d81d3c7441208b84c9f6f97b2a25757d19c0b444f',
		address: '0x0000000000000000000000000000000000274Fa8',
		topics: [Array],
		data: '0x00000000000000000000000000000000000000000000000000000000000003e8',
		logIndex: 0,
		blockHash: '0xb8553decd07d595c77eaa17c019e0f506ab0632da614971b006a6b1353d5e57a',
		args: [Array],
		decode: [Function (anonymous)],
		event: 'Transfer',
		eventSignature: 'Transfer(address,address,uint256)',
		removeListener: [Function (anonymous)],
		getBlock: [Function (anonymous)],
		getTransaction: [Function (anonymous)],
		getTransactionReceipt: [Function (anonymous)]
	}
	]
}
- Balance of the Vault contract before the withdraw 1000
- Withdraw tokens from the Vault contract {
	to: '0x0000000000000000000000000000000000274faF',
	from: '0x398520c72090d7aaBe37e2c49ab1cAe8e662AEa0',
	contractAddress: '0x0000000000000000000000000000000000274faF',
	transactionIndex: 0,
	gasUsed: BigNumber { _hex: '0x0c3500', _isBigNumber: true },
	logsBloom: '0x00800000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000008000000000000000000000000000000000000000000000004000000000000000000000000100000000000000000000010000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000080000000000000000',
	blockHash: '0x3de5a72720f9b221d5e436b2ccaf3b1219436d653a943528a20569ba94ee397b',
	transactionHash: '0x7a661f21f9dd4a99764b4f5f216f29ff5a20207cd4f57d0ca1a25f12af2e6d2b',
	logs: [
	{
		transactionIndex: 0,
		blockNumber: 2490835,
		transactionHash: '0x7a661f21f9dd4a99764b4f5f216f29ff5a20207cd4f57d0ca1a25f12af2e6d2b',
		address: '0x0000000000000000000000000000000000274Fa8',
		topics: [Array],
		data: '0x00000000000000000000000000000000000000000000000000000000000003e8',
		logIndex: 0,
		blockHash: '0x3de5a72720f9b221d5e436b2ccaf3b1219436d653a943528a20569ba94ee397b'
	}
	],
	blockNumber: 2490835,
	confirmations: 1,
	cumulativeGasUsed: BigNumber { _hex: '0x0c3500', _isBigNumber: true },
	effectiveGasPrice: BigNumber { _hex: '0x03179fcad000', _isBigNumber: true },
	status: 1,
	type: 2,
	byzantium: true,
	events: [
	{
		transactionIndex: 0,
		blockNumber: 2490835,
		transactionHash: '0x7a661f21f9dd4a99764b4f5f216f29ff5a20207cd4f57d0ca1a25f12af2e6d2b',
		address: '0x0000000000000000000000000000000000274Fa8',
		topics: [Array],
		data: '0x00000000000000000000000000000000000000000000000000000000000003e8',
		logIndex: 0,
		blockHash: '0x3de5a72720f9b221d5e436b2ccaf3b1219436d653a943528a20569ba94ee397b',
		removeListener: [Function (anonymous)],
		getBlock: [Function (anonymous)],
		getTransaction: [Function (anonymous)],
		getTransactionReceipt: [Function (anonymous)]
	}
	]
}
- Balance of the Vault contract after the withdraw 0

Congratulations! 🎉 You have successfully learned to use native Hedera tokens as ERC20 tokens. Feel free to reach out if you have any questions:

To make the setup process simple, you'll use a pre-configured token wrapper project from the token-wrapper .

The JSON_RPC_RELAY_URL variable contains the Testnet endpoint URL. This is the JSON-RPC instance that will submit the transactions to the Hedera test network to test, create and deploy your smart contract.

In this step, you'll examine the descriptions of the project contents in your existing project. If you don't need to review the project contents, you can proceed directly to .

To see the transactions on the Hedera network, you can use the .

repository
HashIO
Hedera Testnet Explorer
Running the project
Hashio
TypeScript
Solidity
Hedera testnet account
ts-node
Project Setup
Project Configuration
Project Contents
Running the Project

Writer: Lucía, Developer

(Hashgraph Association)

Editor: Krystal, Technical Writer

1.

2.

3.

4.

| |

|

GitHub
Twitter
LinkedIn
GitHub
Twitter
PREREQUISITES
PROJECT SETUP
PROJECT CONTENTS
RUNNING THE PROJECT