Skip to main content

Technical Details

This page covers technical specifications for working with ERC token data on Hedera, including account identifiers, event signatures, and data formats.

In Beta → Hgraph's Hedera ERC Token Data

This new data service is currently in beta and we encourage all users to provide feedback. Please contact us to share your input.

Data Pipeline Overview

The Hedera ERC Indexer processes token data through an eight-stage pipeline:

Key Pipeline Stages

  1. Discovery: Scans Hedera mirror node for contracts emitting Transfer events
  2. Extraction: Retrieves token metadata (name, symbol, decimals) via JSON-RPC
  3. Balance Calculation: Processes all Transfer events to compute current balances
  4. NFT Tracking: For ERC-721 tokens, tracks individual NFT ownership and metadata
  5. Storage: Persists data to erc_beta schema tables
  6. Stream Processing: Continuously polls for new data and updates
  7. API Layer: Exposes data through Hasura GraphQL endpoint
  8. Query Interface: Provides real-time access to token data via GraphQL

Account Identifiers and Aliases

Understanding Hedera Account Systems

Every entity on Hedera has a unique account ID (e.g., 0.0.12345), but accounts can be referenced through multiple identifiers:

1. Account Number (Native Hedera Format)

  • Format: <shard>.<realm>.<account_number> (e.g., 0.0.924713)
  • Usage: Native Hedera transactions and queries
  • In Topics: Stored as 1-8 bytes depending on size

2. Account-num Alias (Long-zero Address)

  • Format: 20-byte EVM address with 12 leading zeros
  • Example: 0x00000000000000000000000000000e1c29 (Account 924713)
  • Purpose: Makes every Hedera account EVM-compatible
  • Resolution: Direct calculation from bytes (no lookup needed)

3. ECDSA EVM Alias

  • Format: Standard 20-byte Ethereum address
  • Example: 0x6d9f1a927cbcb5e2c28d13ca735bc6d6131406da
  • Purpose: Allows MetaMask and EVM wallets to interact with Hedera
  • Resolution: Requires lookup to map to Hedera account ID

Hollow Accounts and Auto-Creation

When an EVM address receives tokens or HBAR before having a Hedera account:

  1. Hollow Account Creation: System automatically creates an incomplete account
  2. Properties: Has account ID and alias, but no key (can receive but not send)
  3. Completion: Becomes full account when used as fee payer with proper signature
  4. Important: Every hollow account still has a unique Hedera ID

Event Detection & Signatures

Transfer Event

All ERC-20 and ERC-721 tokens emit a standardized Transfer event:

event Transfer(address indexed from, address indexed to, uint256 value_or_tokenId)

Event Signature Hash:

0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef

This signature is the keccak256 hash of the event declaration and is always the same for all ERC Transfer events.

Approval Event

event Approval(address indexed owner, address indexed spender, uint256 value)

Event Signature Hash:

0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925

Token Type Detection

The indexer distinguishes token types by analyzing event structure:

ERC-20 Detection

  • Characteristic: topic3 IS NULL
  • Reason: Transfer value is stored in the event's data section
  • Structure: Transfer(from, to, amount) - amount goes in data section

ERC-721 Detection

  • Characteristic: topic3 IS NOT NULL
  • Reason: Unique tokenId is indexed and gets its own topic slot
  • Structure: Transfer(from, to, tokenId) - tokenId becomes topic3

Standard ERC Methods

Both ERC-20 and ERC-721 tokens implement standard methods that the indexer queries:

Common Methods (Both Standards)

function name() external view returns (string memory);
function symbol() external view returns (string memory);

ERC-20 Specific Methods

function decimals() external view returns (uint8);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);

ERC-721 Specific Methods

function totalSupply() external view returns (uint256);  // Optional
function ownerOf(uint256 tokenId) external view returns (address);
function tokenURI(uint256 tokenId) external view returns (string memory);

Reliability Scoring

The indexer calculates quality scores based on metadata completeness to help identify well-formed contracts.

Scoring Methodology

The metadata_reliability_score field indicates how many standard methods returned valid data:

ERC-20 Tokens (4 fields)

Fields checked: name, symbol, decimals, totalSupply

ScoreFields ExtractedMeaning
1.004 of 4Fully compliant ERC-20
0.753 of 4Mostly compliant
0.502 of 4Partial implementation
0.251 of 4Minimal implementation
0.000 of 4No metadata available

ERC-721 NFTs (3 fields)

Fields checked: name, symbol, totalSupply (decimals not applicable)

ScoreFields ExtractedMeaning
1.003 of 3Fully compliant ERC-721
0.672 of 3Mostly compliant
0.331 of 3Minimal implementation
0.000 of 3No metadata available

Unknown/Failed Deployments

For contracts that couldn't be identified as ERC-20 or ERC-721:

ScoreFields ExtractedMeaning
1.00name AND symbolBasic token interface
0.50name OR symbolPartial interface
0.00NeitherNo standard interface

Using Reliability Scores

Filter for high-quality tokens in your queries:

query ReliableTokens {
erc_beta_token(
where: {
metadata_reliability_score: { _gte: 0.75 }
contract_type: { _in: ["ERC_20", "ERC_721"] }
}
) {
name
symbol
metadata_reliability_score
}
}

Data Encoding Formats

Address Encoding

Addresses in the GraphQL API are always returned as strings in hex format with 0x prefix:

  • EVM Addresses: 0x + 40 hex characters
  • Example: 0x00000000000000000000000000000000002cc823

Numeric Values

Large numbers (balances, token supplies) are returned as strings to preserve precision:

  • Format: Decimal string representation
  • Example: "1000000000000000000" (1 token with 18 decimals)
  • Max Value: Full uint256 range (2^256 - 1)

Timestamps

Two timestamp formats are used:

Field TypeFormatExampleDescription
created_timestampNanoseconds1698765432100000000Hedera consensus time
balance_timestampNanoseconds1698765432100000000Last balance update
processing_timestampSeconds1698765432Unix timestamp

Working with Token Balances

ERC-20 Balances

Balances are stored in the smallest unit (wei):

// Convert balance to human-readable format
function formatBalance(balance, decimals) {
return (BigInt(balance) / BigInt(10 ** decimals)).toString();
}

// Example: 1000000000000000000 with 18 decimals = 1 token

ERC-721 Balances

For NFTs, the balance represents the count of NFTs owned:

query NFTCount($accountId: bigint!, $tokenId: bigint!) {
erc_beta_token_account(
where: {
account_id: { _eq: $accountId }
token_id: { _eq: $tokenId }
}
) {
balance # This is the NFT count, not wei
}
}