# Get account by alias, id, or evm address Source: https://docs.hedera.com/api-reference/accounts/get-account-by-alias-id-or-evm-address /openapi.yaml get /api/v1/accounts/{idOrAliasOrEvmAddress} Return the account transactions and balance information given an account alias, an account id, or an evm address. The information will be limited to at most 1000 token balances for the account as outlined in HIP-367. When the timestamp parameter is supplied, we will return transactions and account state for the relevant timestamp query. Balance information will be accurate to within 15 minutes of the provided timestamp query. Historical ethereum nonce information is currently not available and may not be the exact value at a provided timestamp. # Get crypto allowances for an account info Source: https://docs.hedera.com/api-reference/accounts/get-crypto-allowances-for-an-account-info /openapi.yaml get /api/v1/accounts/{idOrAliasOrEvmAddress}/allowances/crypto Returns information for all crypto allowances for an account. # Get fungible token allowances for an account Source: https://docs.hedera.com/api-reference/accounts/get-fungible-token-allowances-for-an-account /openapi.yaml get /api/v1/accounts/{idOrAliasOrEvmAddress}/allowances/tokens Returns information for fungible token allowances for an account. ## Ordering The order is governed by a combination of the spender id and the token id values, with spender id being the parent column. The token id value governs its order within the given spender id. Note: The default order for this API is currently ASC ## Filtering When filtering there are some restrictions enforced to ensure correctness and scalability. **The table below defines the restrictions and support for the endpoint** | Query Param | Comparison Operator | Support | Description | Example | | ------------- | ------------------- | ------- | --------------------- | ------- | | spender.id | eq | Y | Single occurrence only. | ?spender.id=X | | | ne | N | | | | | lt(e) | Y | Single occurrence only. | ?spender.id=lte:X | | | gt(e) | Y | Single occurrence only. | ?spender.id=gte:X | | token.id | eq | Y | Single occurrence only. Requires the presence of a **spender.id** query | ?token.id=lt:Y | | | ne | N | | | | | lt(e) | Y | Single occurrence only. Requires the presence of an **lte** or **eq** **spender.id** query | ?spender.id=lte:X&token.id=lt:Y | | | gt(e) | Y | Single occurrence only. Requires the presence of an **gte** or **eq** **spender.id** query | ?spender.id=gte:X&token.id=gt:Y | Both filters must be a single occurrence of **gt(e)** or **lt(e)** which provide a lower and or upper boundary for search. # Get nfts for an account info Source: https://docs.hedera.com/api-reference/accounts/get-nfts-for-an-account-info /openapi.yaml get /api/v1/accounts/{idOrAliasOrEvmAddress}/nfts Returns information for all non-fungible tokens for an account. ## Ordering When considering NFTs, their order is governed by a combination of their numerical **token.Id** and **serialnumber** values, with **token.id** being the parent column. A serialnumbers value governs its order within the given token.id In that regard, if a user acquired a set of NFTs in the order (2-2, 2-4 1-5, 1-1, 1-3, 3-3, 3-4), the following layouts illustrate the ordering expectations for ownership listing 1. **All NFTs in ASC order**: 1-1, 1-3, 1-5, 2-2, 2-4, 3-3, 3-4 2. **All NFTs in DESC order**: 3-4, 3-3, 2-4, 2-2, 1-5, 1-3, 1-1 3. **NFTs above 1-1 in ASC order**: 1-3, 1-5, 2-2, 2-4, 3-3, 3-4 4. **NFTs below 3-3 in ASC order**: 1-1, 1-3, 1-5, 2-2, 2-4 5. **NFTs between 1-3 and 3-3 inclusive in DESC order**: 3-4, 3-3, 2-4, 2-2, 1-5, 1-3 Note: The default order for this API is currently DESC ## Filtering When filtering there are some restrictions enforced to ensure correctness and scalability. **The table below defines the restrictions and support for the NFT ownership endpoint** | Query Param | Comparison Operator | Support | Description | Example | | ------------- | ------------------- | ------- | --------------------- | ------- | | token.id | eq | Y | Single occurrence only. | ?token.id=X | | | ne | N | | | | | lt(e) | Y | Single occurrence only. | ?token.id=lte:X | | | gt(e) | Y | Single occurrence only. | ?token.id=gte:X | | serialnumber | eq | Y | Single occurrence only. Requires the presence of a **token.id** query | ?serialnumber=Y | | | ne | N | | | | | lt(e) | Y | Single occurrence only. Requires the presence of an **lte** or **eq** **token.id** query | ?token.id=lte:X&serialnumber=lt:Y | | | gt(e) | Y | Single occurrence only. Requires the presence of an **gte** or **eq** **token.id** query | ?token.id=gte:X&serialnumber=gt:Y | | spender.id | eq | Y | | ?spender.id=Z | | | ne | N | | | | | lt(e) | Y | | ?spender.id=lt:Z | | | gt(e) | Y | | ?spender.id=gt:Z | Note: When searching across a range for individual NFTs a **serialnumber** with an additional **token.id** query filter must be provided. Both filters must be a single occurrence of **gt(e)** or **lt(e)** which provide a lower and or upper boundary for search. # Get non fungible token allowances for an account Source: https://docs.hedera.com/api-reference/accounts/get-non-fungible-token-allowances-for-an-account /openapi.yaml get /api/v1/accounts/{idOrAliasOrEvmAddress}/allowances/nfts Returns an account's non-fungible token allowances. ## Ordering The order is governed by a combination of the account ID and the token ID values, with account ID being the parent column. The token ID value governs its order within the given account ID. Note: The default order for this API is currently ascending. The account ID can be the owner or the spender ID depending upon the owner flag. ## Filtering When filtering there are some restrictions enforced to ensure correctness and scalability. **The table below defines the restrictions and support for the endpoint** | Query Param | Comparison Operator | Support | Description | Example | | ------------- | ------------------- | ------- | --------------------- | ------- | | account.id | eq | Y | Single occurrence only. | ?account.id=X | | | ne | N | | | | | lt(e) | Y | Single occurrence only. | ?account.id=lte:X | | | gt(e) | Y | Single occurrence only. | ?account.id=gte:X | | token.id | eq | Y | Single occurrence only. Requires the presence of an **account.id** parameter | ?account.id=X&token.id=eq:Y | | | ne | N | | | | | lt(e) | Y | Single occurrence only. Requires the presence of an **lte** or **eq** **account.id** parameter | ?account.id=lte:X&token.id=lt:Y | | | gt(e) | Y | Single occurrence only. Requires the presence of an **gte** or **eq** **account.id** parameter | ?account.id=gte:X&token.id=gt:Y | Both filters must be a single occurrence of **gt(e)** or **lt(e)** which provide a lower and or upper boundary for search. # Get past staking reward payouts for an account Source: https://docs.hedera.com/api-reference/accounts/get-past-staking-reward-payouts-for-an-account /openapi.yaml get /api/v1/accounts/{idOrAliasOrEvmAddress}/rewards Returns information for all past staking reward payouts for an account. # Get token relationships info for an account Source: https://docs.hedera.com/api-reference/accounts/get-token-relationships-info-for-an-account /openapi.yaml get /api/v1/accounts/{idOrAliasOrEvmAddress}/tokens Returns information for all token relationships for an account. # List account entities on network Source: https://docs.hedera.com/api-reference/accounts/list-account-entities-on-network /openapi.yaml get /api/v1/accounts Returns a list of all account entity items on the network. # Get outstanding token airdrops sent by an account Source: https://docs.hedera.com/api-reference/airdrops/get-outstanding-token-airdrops-sent-by-an-account /openapi.yaml get /api/v1/accounts/{idOrAliasOrEvmAddress}/airdrops/outstanding Returns outstanding token airdrops that have been sent by an account. # Get pending token airdrops received by an account Source: https://docs.hedera.com/api-reference/airdrops/get-pending-token-airdrops-received-by-an-account /openapi.yaml get /api/v1/accounts/{idOrAliasOrEvmAddress}/airdrops/pending Returns pending token airdrops that have been received by an account. # List account balances Source: https://docs.hedera.com/api-reference/balances/list-account-balances /openapi.yaml get /api/v1/balances Returns a list of account and token balances on the network. The latest balance information is returned when there is no timestamp query parameter, otherwise, the information is retrieved from snapshots with 15-minute granularity. This information is limited to at most 50 token balances per account as outlined in HIP-367. As such, it's not recommended for general use and we instead recommend using either `/api/v1/accounts/{id}/tokens` or `/api/v1/tokens/{id}/balances` to obtain the current token balance information and `/api/v1/accounts/{id}` to return the current account balance. # Get block by hash or number Source: https://docs.hedera.com/api-reference/blocks/get-block-by-hash-or-number /openapi.yaml get /api/v1/blocks/{hashOrNumber} Returns the block information by given hash or number. # List blocks Source: https://docs.hedera.com/api-reference/blocks/list-blocks /openapi.yaml get /api/v1/blocks Returns a list of blocks on the network. # Get verified contract Source: https://docs.hedera.com/api-reference/contract-lookup/get-verified-contract /smart-contract-verification-api.yaml get /v2/contract/{chainId}/{address} By default returns minimal information about the contract: `match`, `creation_match`, `runtime_match`, `chainId`, `address`, and `verifiedAt` To get other details one can either list the fields requested in the `fields` query param or ask all fields but omit several with `omit`. To get everything just pass `fields=all`. # Get verified contract at an address on all chains Source: https://docs.hedera.com/api-reference/contract-lookup/get-verified-contract-at-an-address-on-all-chains /smart-contract-verification-api.yaml get /v2/contract/all-chains/{address} Returns all verified deployments at an address on all Sourcify chains (including deprecated ones). Success returns an array of VerifiedContractMinimal objects under `results` field. If not verified on any chain, the `results` array will be empty. # List of verified contracts per chain Source: https://docs.hedera.com/api-reference/contract-lookup/list-of-verified-contracts-per-chain /smart-contract-verification-api.yaml get /v2/contracts/{chainId} Retrieve the verified contracts on a chain # Get contract by id Source: https://docs.hedera.com/api-reference/contracts/get-contract-by-id /openapi.yaml get /api/v1/contracts/{contractIdOrAddress} Return the contract information given an id # Get the contract actions from a contract on the network for a given transactionId or ethereum transaction hash Source: https://docs.hedera.com/api-reference/contracts/get-the-contract-actions-from-a-contract-on-the-network-for-a-given-transactionid-or-ethereum-transaction-hash /openapi.yaml get /api/v1/contracts/results/{transactionIdOrHash}/actions Returns a list of ContractActions for a contract's function executions for a given transactionId or ethereum transaction hash. # Get the contract result from a contract on the network executed at a given timestamp Source: https://docs.hedera.com/api-reference/contracts/get-the-contract-result-from-a-contract-on-the-network-executed-at-a-given-timestamp /openapi.yaml get /api/v1/contracts/{contractIdOrAddress}/results/{timestamp} Returns a single ContractResult for a contract's function executions at a specific timestamp. # Get the contract result from a contract on the network for a given transactionId or ethereum transaction hash Source: https://docs.hedera.com/api-reference/contracts/get-the-contract-result-from-a-contract-on-the-network-for-a-given-transactionid-or-ethereum-transaction-hash /openapi.yaml get /api/v1/contracts/results/{transactionIdOrHash} Returns a single ContractResult for a contract's function executions for a given transactionId or ethereum transaction hash. # Get the opcode traces for a historical transaction on the network with the given transaction ID or hash Source: https://docs.hedera.com/api-reference/contracts/get-the-opcode-traces-for-a-historical-transaction-on-the-network-with-the-given-transaction-id-or-hash /openapi.yaml get /api/v1/contracts/results/{transactionIdOrHash}/opcodes Re-executes a transaction and returns a result containing detailed information for the execution, including all values from the {@code stack}, {@code memory} and {@code storage} and the entire trace of opcodes that were executed during the replay. Note that to provide the output, the transaction needs to be re-executed on the EVM, which may take a significant amount of time to complete if stack and memory information is requested. # Invoke a smart contract Source: https://docs.hedera.com/api-reference/contracts/invoke-a-smart-contract /openapi.yaml post /api/v1/contracts/call Returns a result from EVM execution such as cost-free execution of read-only smart contract queries, gas estimation, and transient simulation of read-write operations. If the `estimate` field is set to true gas estimation is executed. This API can process calls against the `latest` block or specific historical blocks when a hexadecimal or decimal block number is provided in the `block` field. # List contract entities on network Source: https://docs.hedera.com/api-reference/contracts/list-contract-entities-on-network /openapi.yaml get /api/v1/contracts Returns a list of all contract entity items on the network. # List contract logs from a contract on the network Source: https://docs.hedera.com/api-reference/contracts/list-contract-logs-from-a-contract-on-the-network /openapi.yaml get /api/v1/contracts/{contractIdOrAddress}/results/logs Search the logs of a specific contract across multiple contract calls. Chained logs are not included but can be found by calling `/api/v1/contracts/{contractId}/results/{timestamp}` or `/api/v1/contracts/results/{transactionId}`. When searching by topic a timestamp parameter must be supplied and span a time range of at most seven days. ## Ordering The order is governed by the combination of timestamp and index values. If the index param is omitted, the order is determined by the timestamp only. Note: The default order for this API is currently DESC ## Filtering When filtering there are some restrictions enforced to ensure correctness and scalability. **The table below defines the restrictions and support for the endpoint** | Query Param | Comparison Operator | Support | Description | Example | | ------------- | ------------------- | ------- | --------------------- | ------- | | index | eq | Y | Single occurrence only. Requires the presence of timestamp | ?index=X | | | ne | N | | | | | lt(e) | Y | Single occurrence only. Requires the presence of timestamp | ?index=lte:X | | | gt(e) | Y | Single occurrence only. Requires the presence of timestamp | ?index=gte:X | | timestamp | eq | Y | Single occurrence only. | ?timestamp=Y | | ne | N | | | | | lt(e) | Y | Single occurrence only. Optional second timestamp **gt(e)** | ?timestamp=lte:Y | | gt(e) | Y | Single occurrence only. Optional second timestamp **lt(e)** | ?timestamp=gte:Y Both filters must be a single occurrence of **gt(e)** or **lt(e)** which provide a lower and or upper boundary for search. # List contract results from a contract on the network Source: https://docs.hedera.com/api-reference/contracts/list-contract-results-from-a-contract-on-the-network /openapi.yaml get /api/v1/contracts/{contractIdOrAddress}/results Returns a list of all ContractResults for a contract's function executions. # List contract results from all contracts on the network Source: https://docs.hedera.com/api-reference/contracts/list-contract-results-from-all-contracts-on-the-network /openapi.yaml get /api/v1/contracts/results Returns a list of all ContractResults for all contract's function executions. # List contracts logs across many contracts on the network Source: https://docs.hedera.com/api-reference/contracts/list-contracts-logs-across-many-contracts-on-the-network /openapi.yaml get /api/v1/contracts/results/logs Search the logs across many contracts with multiple contract calls. Chained logs are not included but can be found by calling `/api/v1/contracts/{contractId}/results/{timestamp}` or `/api/v1/contracts/results/{transactionId}`. When searching by topic a timestamp parameter must be supplied and span a time range of at most seven days. ## Ordering The order is governed by the combination of timestamp and index values. If the index param is omitted, the order is determined by the timestamp only. Note: The default order for this API is currently DESC ## Filtering When filtering there are some restrictions enforced to ensure correctness and scalability. **The table below defines the restrictions and support for the endpoint** | Query Param | Comparison Operator | Support | Description | Example | | ------------- | ------------------- | ------- | --------------------- | ------- | | index | eq | Y | Single occurrence only. Requires the presence of timestamp | ?index=X | | | ne | N | | | | | lt(e) | Y | Single occurrence only. Requires the presence of timestamp | ?index=lte:X | | | gt(e) | Y | Single occurrence only. Requires the presence of timestamp | ?index=gte:X | | timestamp | eq | Y | Single occurrence only. | ?timestamp=Y | | ne | N | | | | | lt(e) | Y | Single occurrence only. Optional second timestamp **gt(e)** | ?timestamp=lte:Y | | gt(e) | Y | Single occurrence only. Optional second timestamp **lt(e)** | ?timestamp=gte:Y Both filters must be a single occurrence of **gt(e)** or **lt(e)** which provide a lower and or upper boundary for search. # The contract state from a contract on the network Source: https://docs.hedera.com/api-reference/contracts/the-contract-state-from-a-contract-on-the-network /openapi.yaml get /api/v1/contracts/{contractIdOrAddress}/state Returns a list of all contract's slots. If no timestamp is provided, returns the current state. # List all components Source: https://docs.hedera.com/api-reference/list-all-components /hedera-status-api.yaml get /components.json Provides detailed information about each component of the Hedera network. # Estimate network fees Source: https://docs.hedera.com/api-reference/network/estimate-network-fees /openapi.yaml post /api/v1/network/fees Given a protobuf-encoded HAPI transaction, returns an itemized fee estimate in tinycents. The response is broken down into `node`, `network`, and `service` components, each with a `base` price and a list of `extras` (e.g., signatures, memo bytes). The `total` field is the sum of all subtotals. When the request transaction sets the [HIP-1313](https://hips.hedera.com/hip/hip-1313) `high_volume` flag, the response includes a `high_volume_multiplier`. The totals in the response are **not** pre-multiplied — multiply `total` by `high_volume_multiplier / 1000` to obtain the high-volume price. # Get network stake information Source: https://docs.hedera.com/api-reference/network/get-network-stake-information /openapi.yaml get /api/v1/network/stake Returns the network's current stake information. # Get registered nodes Source: https://docs.hedera.com/api-reference/network/get-registered-nodes /openapi.yaml get /api/v1/network/registered-nodes Returns the list of registered nodes # Get the network address book nodes Source: https://docs.hedera.com/api-reference/network/get-the-network-address-book-nodes /openapi.yaml get /api/v1/network/nodes Returns the network's list of nodes used in consensus # Get the network exchange rate to estimate costs Source: https://docs.hedera.com/api-reference/network/get-the-network-exchange-rate-to-estimate-costs /openapi.yaml get /api/v1/network/exchangerate Returns the network's exchange rate, current and next. # Get the network fees Source: https://docs.hedera.com/api-reference/network/get-the-network-fees /openapi.yaml get /api/v1/network/fees Returns the estimated gas in tinybars per each transaction type. Default order is ASC. Currently only `ContractCall`, `ContractCreate` and `EthereumTransaction` transaction types are supported. # Get the network supply Source: https://docs.hedera.com/api-reference/network/get-the-network-supply /openapi.yaml get /api/v1/network/supply Returns the network's released supply of hbars # Get the list of supported and deprecated chains Source: https://docs.hedera.com/api-reference/other/get-the-list-of-supported-and-deprecated-chains /smart-contract-verification-api.yaml get /chains # Get version information Source: https://docs.hedera.com/api-reference/other/get-version-information /smart-contract-verification-api.yaml get /version Returns version information for the server and its dependencies, along with the git commit hash # Health check endpoint Source: https://docs.hedera.com/api-reference/other/health-check-endpoint /smart-contract-verification-api.yaml get /health Returns server health status # Retrieve a summary of the status page. Source: https://docs.hedera.com/api-reference/retrieve-a-summary-of-the-status-page /hedera-status-api.yaml get /summary.json Get a summary of the status page, including a status indicator, component statuses, unresolved incidents, and any upcoming or in-progress scheduled maintenances. # Retrieve active scheduled maintenances Source: https://docs.hedera.com/api-reference/retrieve-active-scheduled-maintenances /hedera-status-api.yaml get /scheduled-maintenances/active.json Fetches details about all currently active scheduled maintenance events for the Hedera network. # Retrieve all incidents Source: https://docs.hedera.com/api-reference/retrieve-all-incidents /hedera-status-api.yaml get /incidents.json Fetches a list of all incidents, both resolved and unresolved, affecting the Hedera network. # Retrieve all scheduled maintenances Source: https://docs.hedera.com/api-reference/retrieve-all-scheduled-maintenances /hedera-status-api.yaml get /scheduled-maintenances.json Fetches details about all scheduled maintenance events for the Hedera network. # Retrieve the current status of the Hedera network Source: https://docs.hedera.com/api-reference/retrieve-the-current-status-of-the-hedera-network /hedera-status-api.yaml get /status.json Fetches the overall status and health indicators of the Hedera network. # Retrieve unresolved incidents Source: https://docs.hedera.com/api-reference/retrieve-unresolved-incidents /hedera-status-api.yaml get /incidents/unresolved.json Provides information about all currently unresolved incidents affecting the Hedera network. # Retrieve upcoming scheduled maintenances Source: https://docs.hedera.com/api-reference/retrieve-upcoming-scheduled-maintenances /hedera-status-api.yaml get /scheduled-maintenances/upcoming.json Provides information about all upcoming scheduled maintenance events for the Hedera network. # Get schedule by id Source: https://docs.hedera.com/api-reference/schedules/get-schedule-by-id /openapi.yaml get /api/v1/schedules/{scheduleId} Returns schedule information based on the given schedule id # List schedules entities Source: https://docs.hedera.com/api-reference/schedules/list-schedules-entities /openapi.yaml get /api/v1/schedules Lists schedules on the network that govern the execution logic of scheduled transactions. This includes executed and non executed schedules. # Get an nfts transction history Source: https://docs.hedera.com/api-reference/tokens/get-an-nfts-transction-history /openapi.yaml get /api/v1/tokens/{tokenId}/nfts/{serialNumber}/transactions Returns a list of transactions for a given non-fungible token # Get nft info Source: https://docs.hedera.com/api-reference/tokens/get-nft-info /openapi.yaml get /api/v1/tokens/{tokenId}/nfts/{serialNumber} Returns information for a non-fungible token # Get token by id Source: https://docs.hedera.com/api-reference/tokens/get-token-by-id /openapi.yaml get /api/v1/tokens/{tokenId} Returns token entity information given the id # List nfts Source: https://docs.hedera.com/api-reference/tokens/list-nfts /openapi.yaml get /api/v1/tokens/{tokenId}/nfts Returns a list of non-fungible tokens # List token balances Source: https://docs.hedera.com/api-reference/tokens/list-token-balances /openapi.yaml get /api/v1/tokens/{tokenId}/balances Returns a list of token balances given the id. This represents the Token supply distribution across the network # List tokens Source: https://docs.hedera.com/api-reference/tokens/list-tokens /openapi.yaml get /api/v1/tokens Returns a list of tokens on the network. # Get topic by ID Source: https://docs.hedera.com/api-reference/topics/get-topic-by-id /openapi.yaml get /api/v1/topics/{topicId} Returns the topic details for the given topic ID. # Get topic message by consensusTimestamp Source: https://docs.hedera.com/api-reference/topics/get-topic-message-by-consensustimestamp /openapi.yaml get /api/v1/topics/messages/{timestamp} Returns a topic message the given the consensusTimestamp. # Get topic message by id and sequence number Source: https://docs.hedera.com/api-reference/topics/get-topic-message-by-id-and-sequence-number /openapi.yaml get /api/v1/topics/{topicId}/messages/{sequenceNumber} Returns a single topic message for the given topic id and sequence number. # List topic messages by id Source: https://docs.hedera.com/api-reference/topics/list-topic-messages-by-id /openapi.yaml get /api/v1/topics/{topicId}/messages Returns the list of topic messages for the given topic id. # Get transaction by id Source: https://docs.hedera.com/api-reference/transactions/get-transaction-by-id /openapi.yaml get /api/v1/transactions/{transactionId} Returns transaction information based on the given transaction id # List transactions Source: https://docs.hedera.com/api-reference/transactions/list-transactions /openapi.yaml get /api/v1/transactions Lists transactions on the network. This includes successful and unsuccessful transactions. # Check verification job status Source: https://docs.hedera.com/api-reference/verification-jobs/check-verification-job-status /smart-contract-verification-api.yaml get /v2/verify/{verificationId} Endpoint to get the status of a verification job. Alternatively you can directly check the verification status of a contract with with chainId+address at `GET /v2/contract/{chainId}/{address}` # Import from Etherscan Source: https://docs.hedera.com/api-reference/verify-contracts/import-from-etherscan /smart-contract-verification-api.yaml post /v2/verify/etherscan/{chainId}/{address} Import a contract verified on an Etherscan instance or a service with Etherscan-alike API # Verify Contract (Standard JSON) Source: https://docs.hedera.com/api-reference/verify-contracts/verify-contract-standard-json /smart-contract-verification-api.yaml post /v2/verify/{chainId}/{address} Submit a contract for verification via the [Solidity standard JSON input](https://docs.soliditylang.org/en/latest/using-the-compiler.html#input-description), [Vyper JSON input](https://docs.vyperlang.org/en/stable/compiling-a-contract.html#input-json-description), or Fe JSON input (a Sourcify-defined format — Fe has no official compiler JSON interface). There are no "single file" or "multi-part" verification endpoints because those are essentially wrappers around the Solidity compiler's JSON interface. The verification frontend can provide files and settings options to resemble these. You can optionally pass the `creationTransactionHash` to make Sourcify reliably fetching the creation bytecode. Otherwise, it will try to fetch it itself which is dependent on external services. **Note**: The `outputSelection` field in the `stdJsonInput.settings` will be overridden during verification to ensure all necessary artifacts are generated. # Verify Contract (using Solidity metadata.json) Source: https://docs.hedera.com/api-reference/verify-contracts/verify-contract-using-solidity-metadatajson /smart-contract-verification-api.yaml post /v2/verify/metadata/{chainId}/{address} Endpoint to submit a verification with the Solidity [metadata.json](https://docs.soliditylang.org/en/latest/metadata.html) # Verify contract via similarity search Source: https://docs.hedera.com/api-reference/verify-contracts/verify-contract-via-similarity-search /smart-contract-verification-api.yaml post /v2/verify/similarity/{chainId}/{address} Starts a verification job that searches the Sourcify database for contracts whose runtime bytecode is similar to the contract deployed at the given address. The job will attempt to verify against each candidate until a match is found or the candidate list is exhausted. # Account Model for EVM Developers Source: https://docs.hedera.com/evm/development/accounts How Hedera accounts work in EVM contexts: EVM addresses map to native account entities, covering hollow accounts, long-zero accounts, and token association. On Hedera, every active EVM address corresponds to a registered account entity with a native **Account ID** (e.g., `0.0.1234`). Unlike Ethereum, where any address can exist implicitly without ever being registered, a Hedera account entity is only created when HBAR or tokens are first sent to an address, or when an account is explicitly created. Understanding this model is important when building dApps that interact with users holding different account types. There are two account types EVM developers encounter in practice: * [**Hollow accounts**](#hollow-accounts) - created automatically when HBAR or tokens are sent to an EVM address for the first time * [**Long-zero accounts**](#long-zero-accounts) - existing Hedera accounts created without an ECDSA key, represented in the EVM by an address padded with leading zeros *** ## Hollow Accounts ### What They Are A hollow account is created automatically by the network when HBAR or tokens are first sent to an EVM address that has no corresponding account yet. This process is called [auto account creation](/learn/core-concepts/accounts/auto-account-creation). The resulting account has: * a native Account ID (e.g., `0.0.5678`) * an EVM address (e.g., `0xabc...def`) stored as the account alias * no signing key on record Because the network has not yet verified which private key controls the address, the account is hollow until completion. ### What Hollow Accounts Can Do EVM tooling works normally with hollow accounts. JSON-RPC calls, Hardhat scripts, Foundry tests, and smart contract interactions all function as expected because the EVM layer does not require a signing key on record. The account can: * receive and hold HBAR and tokens * be the target of contract calls * receive ERC-20 and ERC-721 tokens (Solidity-based token transfers require no Hedera-level association and behave the same as on Ethereum) HTS (native Hedera Token Service) tokens require token association. Hollow accounts are created with `maxAutoAssociations = -1` (unlimited) by default, so they accept HTS token transfers automatically from the moment they are created — no completion required for this. See [HIP-904](https://hips.hedera.com/hip/hip-904). ### What Hollow Accounts Cannot Do A hollow account cannot perform actions that require an authorized key signature until it is completed: * it cannot transfer tokens or HBAR out of the account via HAPI * it cannot modify its own account properties (keys, memo, staking) * it cannot explicitly manage token associations via HAPI ### How Completion Works A hollow account is completed when a transaction is submitted that requires its signature and includes the matching ECDSA key. This most commonly happens in two ways: **Via EVM wallet (automatic):** When the user sends their first outbound transaction from MetaMask or a similar EVM wallet, the wallet signs it with their ECDSA private key. The relay submits it to the network as an `EthereumTransaction`. The network extracts the ECDSA public key from the transaction signature, derives the EVM address from it, matches it against the hollow account's alias, and sets the key on the account to complete it. **Via SDK (explicit):** Build any transaction, set the hollow account as the fee payer, and sign with the ECDSA key that corresponds to the EVM address. ```javascript theme={null} const tx = new TransferTransaction() .addHbarTransfer(hollowAccountId, new Hbar(-1)) .addHbarTransfer(recipientId, new Hbar(1)) .setTransactionId(TransactionId.generate(hollowAccountId)) .freezeWith(client); const signedTx = await tx.sign(ecdsaPrivateKey); await signedTx.execute(client); ``` After completion, the account behaves like any standard Hedera account. ### Looking Up an Account ID from an EVM Address To find the Account ID for a given EVM address, use either of these methods: **Mirror Node REST API:** ``` GET https://mainnet-public.mirrornode.hedera.com/api/v1/accounts/{evmAddress} ``` The response includes the `account` field with the Account ID. **HashScan:** Paste the EVM address into the search bar on [hashscan.io](https://hashscan.io) to see the account details, including its Account ID. *** ## Long-Zero Accounts ### What They Are Many Hedera users hold accounts created through the native HAPI flow, typically with an ED25519 key and no ECDSA alias. These accounts have no EVM Address from Public Key set. When the EVM needs to represent such an account, it constructs a synthetic address by left-padding the account number with zeros to fill 20 bytes. For example, account `0.0.77` becomes `0x000000000000000000000000000000000000004d`. This is called the **EVM Address from Account ID** or the "long-zero" form. | Account ID | Long-Zero EVM Address | | ---------- | -------------------------------------------- | | `0.0.77` | `0x000000000000000000000000000000000000004d` | | `0.0.1000` | `0x00000000000000000000000000000000000003e8` | ### Limitations for EVM Workflows Long-zero accounts cannot participate in standard EVM developer workflows: | Capability | Long-Zero Account | | ---------------------------------------------------- | ---------------------------- | | Sign `EthereumTransaction` (MetaMask, Hardhat, etc.) | No — no ECDSA key | | Connect via EVM wallet | No | | Call smart contracts using EVM tooling | No | | Pass `ECRECOVER`-based signature checks | No — no ECDSA key to recover | | Receive HBAR via EVM transfer | Yes | ### Why This Matters for dApp Developers When building dApps, some of your users will have long-zero accounts. Common failure modes: * **Wallet connection fails silently.** EVM wallets require an ECDSA key. A long-zero account user has no compatible key and cannot connect. * **Permit and off-chain signing flows break.** EIP-2612 and similar patterns rely on `ECRECOVER` to verify signatures. Long-zero accounts cannot produce a valid ECDSA signature, so these checks will fail. * **Access control based on address matching fails.** If your contract stores an expected signer address and validates with `ECRECOVER`, it will never match a long-zero address because recovery requires a valid ECDSA signature. Do not assume all Hedera users can sign EVM transactions. Design fallback flows or clearly communicate wallet requirements to users who may hold long-zero accounts. ### Distinguishing Address Types Both address forms are 20 bytes. You can tell them apart by inspecting the prefix: * **Long-zero:** first 12 bytes are all zeros (`0x000000000000000000000000...`) * **EVM Address from Public Key:** no zero prefix, derived from a Keccak-256 hash ```javascript theme={null} function isLongZero(address) { return address.startsWith("0x000000000000000000000000"); } ``` *** ## Reference | Topic | Link | | ------------------------------------------------------------------ | ----------------------------------------------------------------------------- | | Auto account creation flow | [Auto Account Creation](/learn/core-concepts/accounts/auto-account-creation) | | Account ID and alias properties | [Account Properties](/learn/core-concepts/accounts/account-properties) | | EVM address vs. Account ID differences | [Accounts, Signature Verification & Keys](/evm/differences/accounts-and-keys) | | HIP-32 (auto account creation) | [HIP-32](https://hips.hedera.com/hip/hip-32) | | HIP-542 (ECDSA EVM Address support in CryptoCreate/CryptoTransfer) | [HIP-542](https://hips.hedera.com/hip/hip-542) | | HIP-583 (hollow account completion) | [HIP-583](https://hips.hedera.com/hip/hip-583) | | HIP-904 (frictionless token associations) | [HIP-904](https://hips.hedera.com/hip/hip-904) | # Smart Contract Addresses Source: https://docs.hedera.com/evm/development/addresses After a smart contract is deployed on Hedera, it is associated with a unique smart contract address. There are two types of addresses a smart contract can be referenced by in the system: **➡** [**Smart Contract EVM Address**](#evm-address) **➡** [**Smart Contract ID**](#contract-id) *** ### EVM Address The standard smart contract EVM address is the address that is compatible with EVM. The EVM contract address is returned by the system once the contract is deployed. This is the address format that is commonly used in the Ethereum ecosystem. You can use the smart contract EVM address to reference smart contracts in Ethereum Ecosystem tools like [Hardhat](/support/glossary#hardhat) and [MetaMask](/support/glossary#metamask). Example Contract EVM Address hex encoded contract ID: `0x00000000000000000000000000000000002cd37f` ***Note:** Contracts deployed using the `ContractCreate` Hedera API transactions will have this form (For example, using ContractCreateTransaction in the SDKs). All other deployment cases will be in the standard EVM address, post* [*HIP-729*](https://hips.hedera.com/hip/hip-729)*.* Example Contract EVM Address: [`0x86ecca95fecdb515d068975b75eac4357contractd6e86c5`](https://hashscan.io/mainnet/contract/0.0.2958097?p=1\&k=1685819177.474035003) *** ### Contract ID In the Hedera Network, smart contracts can also be identified by a smart contract ID. A smart contract ID is a contract identifier native to the Hedera network. Both the smart contract EVM address and smart contract ID are accepted identifiers for a smart contract when interacting with the contract on Hedera using the Hedera transactions. Example Contract ID: `0.0.123` In some cases, the EVM address is the hex-encoded format of the contract ID. The smart contract ID is **not a compatible** address format accepted or known in the Ethereum ecosystem. For example, if you use MetaMask, you will not specify the contract by its contract ID and instead use its EVM address. When viewing the contract information, you may see both types of addresses noted in Hedera Network Explorers like [HashScan](https://hashscan.io/). *** ### Smart Contract Accounts Similar to [Ethereum](/support/glossary#ethereum), Smart Contract entities are also a type of account. A smart contract deployed on Hedera can hold [HBAR](/support/glossary#hbar), [fungible](/support/glossary#fungible-token), and [non-fungible tokens](/support/glossary#non-fungible-token-nft).
Smart Contract PropertyExample
Smart Contract ID0.0.2940467
Smart Contract EVM Address0xde2b7414e2918a393b59fc130bceb75c3ee52493
Smart Contract Hex Encoded Contract ID0x00000000000000000000000000000000002cff73
\*This is only present if the contract was NOT deployed via an EVM tool and instead the Hedera SDKs.
Smart Contract Account ID0.0.2940467
# EVM Archive Node Queries Source: https://docs.hedera.com/evm/development/archive-queries ## Introduction to EVM Archive Node Queries [HIP-584](https://hips.hedera.com/hip/hip-584) enhances Hedera Mirror Nodes with extended EVM execution capabilities, allowing developers to perform gas-free smart contract queries, estimate gas usage, and simulate EVM transactions without committing state changes. These enhancements empower developers to: * **Perform Gas-Free Smart Contract Queries:** Retrieve data from smart contracts without incurring gas costs. * **Estimate Gas Usage:** Determine the gas required for executing specific contract functions. * **Simulate EVM Transactions:** Test transactions that involve state changes without committing those changes to the blockchain. This guide uses real examples of interactions with smart contracts, including [SaucerSwap](https://www.saucerswap.finance/)'s DeFi contracts on the Hedera network: * SaucerSwap's HashScan verified DeFi smart contract: * `0x00000000000000000000000000000000002e7a5d` * The HashScan link to the verified smart contract can be found [here](https://hashscan.io/mainnet/contract/0.0.3045981?pf=1\&kf=0.0.1456986). *** ## API Endpoint Overview The API endpoint and parameters used for all operations described in this guide is: ```bash theme={null} POST /api/v1/contracts/call ``` ### Key Parameters * `estimate` (boolean): Determines the operation type. * `true`: Performs gas estimation. * `false`: Executes a query or simulation. * `block` (string): Specifies the block for the operation (e.g., "latest" or a specific block number). * `data` (string): Encoded function call data in hexadecimal format following the ABI specifications. * `from` (string, optional): Address initiating the call. Required for simulations involving state changes. * `to` (string): Target smart contract address (SaucerSwap's DeFi contract for this guide). * `value` (number, optional): Amount of tinybars to send with the transaction. Relevant for simulations involving value transfers. For detailed specifications, refer to the [Swagger documentation](https://testnet.mirrornode.hedera.com/api/v1/docs/#/contracts/contractCall). *** ## Prerequisites Before proceeding, ensure you have: * Basic knowledge of EVM smart contracts: * Understanding of [ABI (Application Binary Interface)](/evm/development/compiling#smart-contract-application-binary-interface-abi) and function encoding. * Essential tools installed and configured: * cURL for making HTTP requests. * Ethers.js (v6 or later or equivalent libraries) for interacting with the EVM-compatible networks. * Function data encoding: * Familiarity with encoding function data into the required EVM-compatible hexadecimal format. *** ## Gas Estimation Estimating gas usage helps determine the cost required to execute a smart contract function without actually performing the transaction. ### **Example Request** Here's how to estimate gas usage using the `/api/v1/contracts/call` endpoint: ```bash wrap theme={null} curl -X POST https://mainnet.mirrornode.hedera.com/api/v1/contracts/call \ -H "Content-Type: application/json" \ -d '{ "block": "latest", "data": "0x1f00ca74000000000000000000000000000000000000000000000000000000003b9aca00000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000163b5a00000000000000000000000000000000000000000000000000000000000b2ad5", "estimate": true, "to": "0x00000000000000000000000000000000002e7a5d" }' ``` ### **Expected Response** The API returns an estimated gas value in hexadecimal format: ```json theme={null} { "result": "0x0000000000007f0d" } ``` ### **Decoding the Result:** To interpret the hexadecimal gas estimate, follow these steps: 1. **Extract the `result`**: the field from the API response containing the gas estimate in hexadecimal format. 2. **Convert Hexadecimal to BigInt**: Use JavaScript's `BigInt` to convert the hexadecimal string to a numerical value. ```javascript theme={null} // Assuming you have the result from the API response const hexString = "0x0000000000007f0d"; const gasEstimate = BigInt(hexString); console.log("Gas Estimate:", gasEstimate.toString()); ``` **Output:** ```bash theme={null} Gas Estimate: 32525 ``` The gas estimate result represents the value in tinybars. **Understanding the Logic** * **Hexadecimal Representation:** Smart contracts and blockchain APIs often use hexadecimal strings to represent numerical values, ensuring precise and compact data transmission. * **Conversion to BigInt:** JavaScript's `BigInt` is used to handle large integers that exceed the safe integer limit of the standard `Number` type, ensuring accuracy in calculations. * **Interpretation:** The numerical value (`32525` in this case) represents the estimated gas required to execute the specified smart contract function. *** ## Contract Queries Contract queries allow developers to retrieve data from smart contracts without altering the blockchain state. This is particularly useful for reading data such as token balances, contract states, and more. ### **Example Request** Retrieve the token balance using a contract’s view function: ```bash wrap theme={null} curl -X POST https://mainnet.mirrornode.hedera.com/api/v1/contracts/call \ -H "Content-Type: application/json" \ -d '{ "block": "latest", "data": "0x1f00ca74000000000000000000000000000000000000000000000000000000003b9aca00000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000163b5a00000000000000000000000000000000000000000000000000000000000b2ad5", "to": "0x00000000000000000000000000000000002e7a5d" }' ``` ### **Expected Response** The API returns the result of the contract’s view function in hexadecimal format: ```json wrap theme={null} { "result": "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000efd80e2d6000000000000000000000000000000000000000000000000000000003b9aca00" } ``` ### Decoding the Result To interpret the hexadecimal result (e.g., token balance), follow these steps: 1. **Extract the** `result`**:** The `result` field contains the data returned by the smart contract function. 2. **Convert Hexadecimal to BigInt:** ```javascript theme={null} const hexString = "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000efd80e2d6000000000000000000000000000000000000000000000000000000003b9aca00"; const balance = BigInt(hexString); console.log("Token Balance:", balance.toString()); ``` **Output:** ```bash theme={null} Token Balance: 32 # value represented in decimal ``` **Understanding the Logic** * **Hexadecimal Representation:** The smart contract's `balanceOf` function returns the token balance in hexadecimal format. * **Conversion to BigInt:** Using `BigInt` ensures accurate representation of potentially large token balances. * **Interpretation:** The numerical value (`32` in this case) represents the token balance of the specified address *** ## EVM Transaction Simulations Simulate EVM transactions (non-view functions) that involve state changes to test contract interactions without committing them. This can be useful for testing token transfers, approvals, and other state-altering functions without changing the blockchain state. ### **Example Request** This example simulates a token transfer by testing contract interactions without altering the state. ```bash wrap theme={null} curl -X POST https://mainnet.mirrornode.hedera.com/api/v1/contracts/call \ -H "Content-Type: application/json" \ -d '{ "block": "latest", "data": "0x", "estimate": false, "from": "0x00000000000000000000000000000000000004e2", "to": "0x00000000000000000000000000000000000004e4", "value": 1000 }' ``` ### **Expected Response** The empty result indicates that the simulation ran successfully without errors: ```json theme={null} { "result": "0x" } ``` *** ## Decoding the Results with Ethers.js To decode the data returned by the Mirror Node, you need the [ABI](/support/glossary#application-binary-interface-abi) of the smart contract you are interacting with. The ABI defines the structure of inputs and outputs for the contract's functions. ### Step 1: Install Ethers.js If you haven't already, install Ethers.js using npm: ```bash theme={null} npm install ethers ``` ### Step 2: Decode the Hexadecimal Result Below is a detailed explanation of how to extract and interpret the `result` from the API response. **Example Scenario** You have made an API request to retrieve a token balance, and received the following response: ```json theme={null} { "result": "0x0000000000007f0d" } ``` You want to convert this hexadecimal result to a human-readable token balance. **JavaScript Code Example** ```javascript theme={null} const { ethers } = require('ethers'); // Example API response const response = { data: { result: "0x0000000000007f0d" // Replace with actual API result } }; // Step 1: Extract the hex string from the API response const hexString = response.data.result; // Step 2: Convert the hexadecimal string to a BigInt const tokenBalance = BigInt(hexString); // Step 3: Display the token balance console.log("Token Balance:", tokenBalance.toString()); ``` **Output:** ```yaml theme={null} Token Balance: 32525 # value represented in decimals ``` **Understanding the Logic** 1. **Extracting the** `result`**:** ```javascript theme={null} const hexString = response.data.result; ``` * **Purpose:** Assign the `result` from the API response to the variable `hexString`. * **Content:** The `hexString` contains the ABI-encoded data returned by the smart contract function. 2. **Converting Hexadecimal to BigInt:** ```javascript theme={null} const tokenBalance = BigInt(hexString); ``` * **Purpose:** Convert the hexadecimal string to a `BigInt` for numerical operations. * **Explanation:** * `BigInt`**:** A JavaScript data type that can represent integers with arbitrary precision, suitable for handling large numbers often used in blockchain applications. * **Conversion:** The `BigInt` constructor automatically parses the hexadecimal string (prefixed with `0x`) and converts it to its numerical equivalent. 3. **Displaying the Token Balance:** ```javascript theme={null} console.log("Token Balance:", tokenBalance.toString()); ``` * **Purpose:** Output the numerical value of the token balance to the console. * **Explanation:** * **`.toString()`:** Converts the `BigInt` to a string for readable output. **Practical Example with Ethers.js for Complex Decoding** For more complex return types (e.g., multiple values, arrays), Ethers.js can be used to decode the `result` based on the contract's ABI. ```javascript wrap theme={null} const { ethers } = require('ethers'); // Example API response const response = { data: { result: "0x000000000000002000000000000000000000000000000000000000000000000020000000efd80e2d6000000000000000000000000000000000000000000000000000000003b9aca00" } }; // Step 1: Extract the hex string from the API response const hexString = response.data.result; // Step 2: Define the ABI for the function you want to decode const abi = [ 'function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts)' ]; // Step 3: Create an interface using the ABI const abiInterface = new ethers.Interface(abi); // Step 4: Decode the result using decodeFunctionResult const decodedResult = abiInterface.decodeFunctionResult('getAmountsIn', hexString); // Step 5: Access the decoded data console.log("Decoded Amounts:", decodedResult[0].toString()); ``` **Output:** ```yaml theme={null} Decoded Amounts: 32525 # value represented in tinybars ``` **Explanation** 1. **Define the ABI:** ```javascript theme={null} const abi = [ 'function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts)' ]; ``` * The ABI specifies the `getAmountsIn` function which returns an array of `uint256` values. 2. **Create an Interface:** ```javascript theme={null} const abiInterface = new ethers.Interface(abi); ``` * `ethers.Interface` uses the ABI to understand how to decode the data. 3. **Decode the Result:** ```javascript theme={null} const decodedResult = abiInterface.decodeFunctionResult('getAmountsIn', hexString); ``` * `decodeFunctionResult` interprets the `result` based on the function's return type. 4. **Access the Decoded Data:** ```javascript theme={null} console.log("Decoded Amounts:", decodedResult[0].toString()); ``` * The decoded result is accessed as `decodedResult[0]` and converted to a string for readability. *** ## Reference * [HIP-584 Proposal](https://hips.hedera.com/hip/hip-584) * [REST API Documentation](/reference/rest-api) * [Swagger Documentation](https://testnet.mirrornode.hedera.com/api/v1/docs/#/contracts/contractCall) * [Ethers.js Documentation](https://docs.ethers.org/v5/) # Compiling Smart Contracts Source: https://docs.hedera.com/evm/development/compiling Compiling a smart contract involves using the contract's source code to generate its [**bytecode**](/support/glossary#bytecode) and the contract [**Application** **Binary Interface (ABI)**](/support/glossary#application-binary-interface-abi). The Ethereum Virtual Machine (EVM) executes the bytecode to understand and execute the smart contract. Meanwhile, other smart contracts use the ABI to understand how to interact with the deployed contracts on the Hedera network. **Compiling Solidity** The compiler for the Solidity programming language is [solc](https://docs.soliditylang.org/en/v0.8.17/installing-solidity.html) ([Solidity](/support/glossary#solidity) Compiler). You can use the compiler directly or embedded in IDEs like [Remix IDE](https://remix.ethereum.org/#lang=en\&optimize=false\&runs=200\&evmVersion=null\&version=soljson-v0.8.18+commit.87f61d96.js) or tools like Hardhat and Truffle. *** ## **Smart Contract Bytecode** Bytecode is the machine-readable language that the EVM uses to execute smart contracts. The compiler analyzes the code, checks for syntax errors, enforces language-specific rules, and generates the corresponding bytecode. **Example:** This is the example bytecode output, produced in hexadecimal format, when the HelloHedera smart contract source code is compiled. ```json theme={null} 608060405234801561001057600080fd5b506040516105583803806105588339818101604052602081101561003357600080fd5b810190808051604051939291908464010000000082111561005357600080fd5b8382019150602082018581111561006957600080fd5b825186600182028301116401000000008211171561008657600080fd5b8083526020830192505050908051906020019080838360005b838110156100ba57808201518184015260208101905061009f565b50505050905090810190601f1680156100e75780820380516001836020036101000a031916815260200191505b50604052505050336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550806001908051906020019061014492919061014b565b50506101e8565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061018c57805160ff19168380011785556101ba565b828001600101855582156101ba579182015b828111156101b957825182559160200191906001019061019e565b5b5090506101c791906101cb565b5090565b5b808211156101e45760008160009055506001016101cc565b5090565b610361806101f76000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80632e9826021461003b57806332af2edb146100f6575b600080fd5b6100f46004803603602081101561005157600080fd5b810190808035906020019064010000000081111561006e57600080fd5b82018360208201111561008057600080fd5b803590602001918460018302840111640100000000831117156100a257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050610179565b005b6100fe6101ec565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561013e578082015181840152602081019050610123565b50505050905090810190601f16801561016b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146101d1576101e9565b80600190805190602001906101e792919061028e565b505b50565b606060018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156102845780601f1061025957610100808354040283529160200191610284565b820191906000526020600020905b81548152906001019060200180831161026757829003601f168201915b5050505050905090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106102cf57805160ff19168380011785556102fd565b828001600101855582156102fd579182015b828111156102fc5782518255916020019190600101906102e1565b5b50905061030a919061030e565b5090565b5b8082111561032757600081600090555060010161030f565b509056fea26469706673582212201644465f5f73dfd73a518b57770f5adb27f025842235980d7a0f4e15b1acb18e64736f6c63430007000033 ``` *** ## **Smart Contract Application Binary Interface (ABI)** The ABI is a JSON (JavaScript Object Notation) file that represents the interface definition for the smart contract. It specifies function signatures, input parameters, return types, and other relevant details of the contract's interface. The ABI helps developers understand how to interact with the smart contract in their distributed applications. **Example:** This is the example ABI output produced when the HelloHedera smart contract is compiled. ```json theme={null} "abi": [ { "inputs": [ { "internalType": "string", "name": "message_", "type": "string" } ], "stateMutability": "nonpayable", "type": "constructor" }, { "inputs": [], "name": "get_message", "outputs": [ { "internalType": "string", "name": "", "type": "string" } ], "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "string", "name": "message_", "type": "string" } ], "name": "set_message", "outputs": [], "stateMutability": "nonpayable", "type": "function" } ] } ``` #### **Additional Resources:** * [Ethereum: Compiling Smart Contracts](https://ethereum.org/en/developers/docs/smart-contracts/compiling/) *** ## Compiling Smart Contract Example **➡** [**Hardhat Tutorial**](/evm/tools/hardhat) ## Additional Resources **➡** [**HTS Precompile Methods**](https://github.com/hiero-ledger/hiero-contracts/blob/main/contracts/token-service/README.md) # Creating Smart Contracts Source: https://docs.hedera.com/evm/development/creating A [smart contract](/support/glossary#smart-contract) is an immutable program consisting of a set of logic (state variables, functions, event handlers, etc.) or rules that can be deployed, stored, and accessed on a [distributed ledger technology](/support/glossary#distributed-ledger-technology-dlt) such as Hedera. The functions contained within a smart contract can update and manage the state of the contract and read data from the deployed contract. They may also create and call other smart contracts functions on the network. Smart contracts are secure, tamper-proof, and transparent, offering a new level of trust and efficiency. Hedera supports any language that compiles to the Ethereum Mainnet. This includes [Solidity](/support/glossary#solidity) and [Vyper](/support/glossary#vyper). These programming languages compile code and produce [bytecode](/support/glossary#bytecode) that the [Ethereum Virtual Machine (EVM)](/support/glossary#ethereum-virtual-machine-evm) can interpret and understand. * To learn more about the Solidity programming language, check out the documentation maintained by the Solidity team [here](https://docs.soliditylang.org/en/v0.8.19/). * To learn more about Vyper, check out the documentation maintained by the Vyper team [here](https://docs.vyperlang.org/en/stable/). In addition, many tools are available to write and compile smart contracts, including the popular [Remix IDE](/support/glossary#remix-ide) and [Hardhat](/support/glossary#hardhat). The Remix IDE is a user-friendly platform that allows you to easily write and compile your smart contracts and perform other tasks such as debugging and testing. Using these tools, you can create powerful and secure smart contracts that can be used for various purposes, from simple token transfers to complex financial instruments. **Example** The following is a very simple example of a smart contract written in the Solidity programming language. The smart contract defines the `owner` and `message` state variables, along with functions like `set_message` (which modifies state details by writing) and `get_message`(which reads state details). ```solidity theme={null} pragma solidity >=0.7.0 <0.8.9; contract HelloHedera { // the contract's owner, set in the constructor address owner; // the message we're storing string message; constructor(string memory message_) { // set the owner of the contract for `kill()` owner = msg.sender; message = message_; } function set_message(string memory message_) public { // only allow the owner to update the message require(msg.sender == owner); message = message_; } // return a string function get_message() public view returns (string memory) { return message; } } ``` *** ## Things you should consider when creating a contract #### **Automatic Token Associations** An auto association slot is one or more slots you approve that allow tokens to be sent to your contract without explicit authorization for each token type. If this property is not set, you must associate each token before it is transferred to the contract for the transfer to be successful via the `TokenAssociateTransaction` in the SDKs. Learn more about auto-token associations [here](/learn/core-concepts/accounts/account-properties#automatic-token-associations). This functionality is exclusively accessible when configuring a `ContractCreateTransaction` API through the Hedera SDKs. If you are deploying a contract on Hedera using EVM tools such as Hardhat and the Hedera JSON RPC Relay, please note that this property cannot be configured, as EVM tools lack compatibility with Hedera's unique features. #### **Admin Key** Contracts have the option to have an [admin key](https://github.com/hashgraph/hedera-protobufs/blob/main/services/contract_create.proto#L117). This concept is native to Hedera contracts and allows the contract account properties to be updated. Note that this does not impact the contract [bytecode](/support/glossary#bytecode) and does not relate to upgradability. If the admin key is not set, you will not be able to update the following Hedera native properties (noted in [ContractUpdateTransactionBody](https://github.com/hashgraph/hedera-protobufs/blob/main/services/contract_update.proto) protobuf) for your contract once it is deployed: * [`autoRenewPeriod`](https://github.com/hashgraph/hedera-protobufs/blob/main/services/contract_update.proto#L78) * [`memoField`](https://github.com/hashgraph/hedera-protobufs/blob/main/services/contract_update.proto#L88) * [`max_automatic_token_associations`](https://github.com/hashgraph/hedera-protobufs/blob/main/services/contract_update.proto#L105) * [`auto_renew_account_id`](https://github.com/hashgraph/hedera-protobufs/blob/main/services/contract_update.proto#L111) * [`staked_id`](https://github.com/hashgraph/hedera-protobufs/blob/main/services/contract_update.proto#L116) * [`decline_reward`](https://github.com/hashgraph/hedera-protobufs/blob/main/services/contract_update.proto#L134) You cannot set the admin key field if you deploy a contract via tools like Hardhat. This field can be set if desired by deploying a contract using one of the Hedera [SDKs](/native/fundamentals). #### **Note** Need to deploy a contract with large bytecode? Hedera supports **jumbo ethereum transactions** ([HIP-1086](https://hips.hedera.com/hip/hip-1086)) to handle big payloads directly, no file uploads required for most cases. *📣 Learn more about jumbo transactions on the* [*Understanding Hedera's EVM Differences and Compatibility*](/evm/differences#jumbo-ethereum-transactions) *and on the* [*`EthereumTransaction` SDK page*](/native/smart-contracts/ethereum-transaction)*.* #### **Max Contract Storage Size** Each contract on Hedera has a storage size limit of 16,384,000 key value pairs (\~500MB). #### **Rent** While rent is not enabled for contracts deployed on Hedera today, you will want to be familiar with the concept of rent, as it may potentially impact the costs of maintaining your contract state on the network. Please refer to the Smart Contract Rent documentation [here](/evm/development/rent). #### **Transaction and Gas Fees** There are Hedera transaction fees and EVM fees associated with deploying a contract. To view the list of base fees, check out the fees page [here](/networks/fees) and the fee estimator calculator [here](https://hedera.com/fees). *** ## Smart Contract FAQs A smart contract is a program that is written in a language that can be interpreted by the EVM. Please refer to the [glossary](/support/glossary) for more keywords and definitions. Hedera supports the official [Ethereum Virtual Machine](https://ethereum.org/en/developers/docs/evm/) and therefore any smart contract language that conforms to standard EVM code, such as Solidity or Vyper. You can use Remix IDE or other Ethereum ecosystem tools to write, compile, and deploy your smart contract on Hedera. Check out our EVM-compatible tools [here](/learn#evm-compatible-tools). On your favorite trusted Block Explorer (also called Mirror Node Explorer on Hedera). To view community-hosted explorers check out the network explorer tools page [here](/networks/community-mirror-nodes-explorers). Hedera supports ERC-20 and ERC-721 token standards and can find the full list of supported standards [here](/evm/tokens). # Deploying Smart Contracts Source: https://docs.hedera.com/evm/development/deploying After compiling your smart contract, you can deploy it to the Hedera network. The constructor's "*init code*" includes the contract's entire bytecode. When deploying, the EVM is expected to be supplied with both the smart contract [bytecode](/support/glossary#bytecode) and the gas required to execute and deploy the contract. Post-deployment, the constructor is removed, leaving only the `runtime_bytecode` for future contract interactions. **➡** [**Hyperledger Besu EVM**](#hyperledger-besu-evm-on-hedera) **➡** [**Cancun Hard Fork**](#cancun-hard-fork) **➡** [**Solidity Variables and Opcodes**](#solidity-variables-and-opcodes) *** ## Ethereum Virtual Machine (EVM) The [Ethereum Virtual Machine (EVM)](/support/glossary#ethereum-virtual-machine-evm) is a run-time environment for executing smart contracts written in EVM native programming languages, like Solidity. The source code must be compiled into bytecode for the EVM to execute a given smart contract. On Hedera, users can interact with the EVM-compatible environment in several ways. They can submit `ContractCreate`, `EthereumTransaction`, or make `eth_sendRawTransaction` RPC calls with the contract bytecode directly. These various paths allow developers to deploy and manage smart contracts efficiently. When the EVM receives the bytecode, it will be further broken down into operation codes ([opcodes](/support/glossary#opcodes)). The EVM opcodes represent the specific instructions it can perform. Each opcode is one byte and has its own gas cost associated with it. The cost per opcode for the Ethereum Cancun hard fork can be found [here](https://www.evm.codes/?fork=cancun). #### Smart Contract Opcode Example ```solidity theme={null} PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x40 MLOAD PUSH2 0x558 CODESIZE SUB DUP1 PUSH2 0x558 DUP4 CODECOPY DUP2 DUP2 ADD PUSH1 0x40 MSTORE PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x33 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 MLOAD PUSH1 0x40 MLOAD SWAP4 SWAP3 SWAP2 SWAP1 DUP5 PUSH5 0x100000000 DUP3 GT ISZERO PUSH2 0x53 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP4 DUP3 ADD SWAP2 POP PUSH1 0x20 DUP3 ADD DUP6 DUP2 GT ISZERO PUSH2 0x69 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP3 MLOAD DUP7 PUSH1 0x1 DUP3 MUL DUP4 ADD GT PUSH5 0x100000000 DUP3 GT OR ISZERO PUSH2 0x86 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP1 DUP4 MSTORE PUSH1 0x20 DUP4 ADD SWAP3 POP POP POP SWAP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xBA JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0x9F JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0xE7 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP PUSH1 0x40 MSTORE POP POP POP CALLER PUSH1 0x0 DUP1 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF MUL NOT AND SWAP1 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND MUL OR SWAP1 SSTORE POP DUP1 PUSH1 0x1 SWAP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 PUSH2 0x144 SWAP3 SWAP2 SWAP1 PUSH2 0x14B JUMP JUMPDEST POP POP PUSH2 0x1E8 JUMP JUMPDEST DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 PUSH1 0x1F ADD PUSH1 0x20 SWAP1 DIV DUP2 ADD SWAP3 DUP3 PUSH1 0x1F LT PUSH2 0x18C JUMPI DUP1 MLOAD PUSH1 0xFF NOT AND DUP4 DUP1 ADD OR DUP6 SSTORE PUSH2 0x1BA JUMP JUMPDEST DUP3 DUP1 ADD PUSH1 0x1 ADD DUP6 SSTORE DUP3 ISZERO PUSH2 0x1BA JUMPI SWAP2 DUP3 ADD JUMPDEST DUP3 DUP2 GT ISZERO PUSH2 0x1B9 JUMPI DUP3 MLOAD DUP3 SSTORE SWAP2 PUSH1 0x20 ADD SWAP2 SWAP1 PUSH1 0x1 ADD SWAP1 PUSH2 0x19E JUMP JUMPDEST JUMPDEST POP SWAP1 POP PUSH2 0x1C7 SWAP2 SWAP1 PUSH2 0x1CB JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST JUMPDEST DUP1 DUP3 GT ISZERO PUSH2 0x1E4 JUMPI PUSH1 0x0 DUP2 PUSH1 0x0 SWAP1 SSTORE POP PUSH1 0x1 ADD PUSH2 0x1CC JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST PUSH2 0x361 DUP1 PUSH2 0x1F7 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 0x36 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x2E982602 EQ PUSH2 0x3B JUMPI DUP1 PUSH4 0x32AF2EDB EQ PUSH2 0xF6 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xF4 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x51 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 PUSH5 0x100000000 DUP2 GT ISZERO PUSH2 0x6E JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP3 ADD DUP4 PUSH1 0x20 DUP3 ADD GT ISZERO PUSH2 0x80 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP2 DUP5 PUSH1 0x1 DUP4 MUL DUP5 ADD GT PUSH5 0x100000000 DUP4 GT OR ISZERO PUSH2 0xA2 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST SWAP2 SWAP1 DUP1 DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP4 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP4 DUP4 DUP1 DUP3 DUP5 CALLDATACOPY PUSH1 0x0 DUP2 DUP5 ADD MSTORE PUSH1 0x1F NOT PUSH1 0x1F DUP3 ADD AND SWAP1 POP DUP1 DUP4 ADD SWAP3 POP POP POP POP POP POP POP SWAP2 SWAP3 SWAP2 SWAP3 SWAP1 POP POP POP PUSH2 0x179 JUMP JUMPDEST STOP JUMPDEST PUSH2 0xFE PUSH2 0x1EC JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x13E JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0x123 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x16B JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x0 DUP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ PUSH2 0x1D1 JUMPI PUSH2 0x1E9 JUMP JUMPDEST DUP1 PUSH1 0x1 SWAP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 PUSH2 0x1E7 SWAP3 SWAP2 SWAP1 PUSH2 0x28E JUMP JUMPDEST POP JUMPDEST POP JUMP JUMPDEST PUSH1 0x60 PUSH1 0x1 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x284 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x259 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x284 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x267 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 PUSH1 0x1F ADD PUSH1 0x20 SWAP1 DIV DUP2 ADD SWAP3 DUP3 PUSH1 0x1F LT PUSH2 0x2CF JUMPI DUP1 MLOAD PUSH1 0xFF NOT AND DUP4 DUP1 ADD OR DUP6 SSTORE PUSH2 0x2FD JUMP JUMPDEST DUP3 DUP1 ADD PUSH1 0x1 ADD DUP6 SSTORE DUP3 ISZERO PUSH2 0x2FD JUMPI SWAP2 DUP3 ADD JUMPDEST DUP3 DUP2 GT ISZERO PUSH2 0x2FC JUMPI DUP3 MLOAD DUP3 SSTORE SWAP2 PUSH1 0x20 ADD SWAP2 SWAP1 PUSH1 0x1 ADD SWAP1 PUSH2 0x2E1 JUMP JUMPDEST JUMPDEST POP SWAP1 POP PUSH2 0x30A SWAP2 SWAP1 PUSH2 0x30E JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST JUMPDEST DUP1 DUP3 GT ISZERO PUSH2 0x327 JUMPI PUSH1 0x0 DUP2 PUSH1 0x0 SWAP1 SSTORE POP PUSH1 0x1 ADD PUSH2 0x30F JUMP JUMPDEST POP SWAP1 JUMP INVALID LOG2 PUSH5 0x6970667358 0x22 SLT KECCAK256 AND DIFFICULTY CHAINID 0x5F 0x5F PUSH20 0xDFD73A518B57770F5ADB27F025842235980D7A0F 0x4E ISZERO 0xB1 0xAC 0xB1 DUP15 PUSH5 0x736F6C6343 STOP SMOD STOP STOP CALLER ``` Reference: [https://ethervm.io/](https://ethervm.io/) *** ## Deployment Options **SDK** You can use a [Hedera SDK](/native/fundamentals) to deploy your smart contract bytecode to the network. This approach does not require using any EVM tools like Hardhat or an instance of the Hedera JSON-RPC Relay. **Hardhat** Hardhat can be used to deploy your smart contract by pointing to a community-hosted [JSON-RPC Relay](/evm/development/json-rpc). However, EVM tools do not support features that are native to Hiero Contracts like: * Admin Key * Contract Memo * Automatic Token Associations * Auto Renew Account ID * Staking Node ID or Account ID * Decline Staking Rewards If you need to set any of the above properties for your contract, you will have to call the `ContractCreateTransaction` API using one of the [Hedera SDKs.](/native/fundamentals) ### Deploying Large Contracts Hedera supports **jumbo Ethereum transactions (**[**HIP-1086**](https://hips.hedera.com/hip/hip-1086)**)** for large bytecode payloads. You can include up to **24KB for contract creation** and **128KB for contract calls** directly in `ethereumData`, without using the File Service (`callDataFileId`). However, jumbo transactions: * Can’t be included in batch transactions (`TransactionList`). * Are subject to network throttling based on bytes per second and per-node limits. #### Bytecode and Gas Essentials When deploying contracts, gas must cover both intrinsic gas and the cost of executing deployment code. Intrinsic gas includes a base fee (21,000) plus a per-byte cost for `callData`: * Intrinsic gas includes a base fee (21,000) plus a per-byte cost for `callData`: * 4 gas per zero byte * 16 gas per non-zero byte #### Example If your contract bytecode is 10KB, with 20% (2KB) as zero bytes and 80% (8KB) as non-zero bytes: * **gas for zero bytes**: 4 × 2,048 = 8,192 * **gas for non-zero bytes**: 16 × 8,192 = 131,072 * **total intrinsic gas** = 21,000 + 8,192 + 131,072 = 160,264 Ensure you adjust `gasLimit` (RLP) and `maxGasAllowance` (wrapper) to cover this total gas. 📣 Learn more on the [Gas and Fees page,](/evm/development/gas-fees) [EthereumTransaction SDK page](/native/smart-contracts/ethereum-transaction), and the [Understanding Hedera's EVM Differences and Compatibility page](/evm/differences). *** ## Hyperledger Besu EVM on Hedera The Hedera network nodes utilize the [HyperLedger Besu EVM ](/support/glossary#hyperledger-besu-evm)Client written in Java as an execution layer for Ethereum-type transactions. The codebase is up to date with the current Ethereum Mainnet hard forks. The Besu EVM client library is used without hooks for Ethereum's consensus, networking, and storage features. Instead, Hedera hooks into its own Hashgraph consensus, Gossip communication, and [Virtual Merkle Trees](/support/glossary#virtual-merkle-tree) components for greater fault tolerance, finality, and scalability. As of the Hedera Mainnet release [`0.50.0`](/networks/release-notes/services#v0.50), the Besu EVM client is configured to support the Cancun hard fork of the Ethereum Mainnet, with some modifications. ### **Cancun Hard Fork** The smart contract platform has been upgraded to support the visible EVM changes introduced in the [Cancun](https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/cancun.md) hard fork. This includes adding new opcodes for transient storage and memory copy, semantic updates for opcodes introduced certain operations introduced in the [Shanghai](https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/shanghai.md), [London](https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/london.md), [Istanbul](https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/istanbul.md), and [Berlin](https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/berlin.md) hard forks, except those with changes in block production, data serialization, and the double fee market. As of the Consensus Node [0.22](/networks/release-notes/services#v0.22) release, gas and input data costs are charged. The amount of intrinsic gas consumed is a constant charge that occurs before any code executes. The intrinsic gas cost is 21,000. The associated cost of input data is 16 gas for each byte of data that is not zero and 4 gas for each byte of data that is zero. The amount of intrinsic gas consumed is charged in relation to the data supplied when making a contract call to the function parameters of external contracts. The gas schedule and the fees table can be found in the gas section of this documentation page. #### Proto-Danksharding As an interim solution to full sharding, introduced in the Cancun hard fork, the proto-danksharding offers some of the advantages of sharding with reduced complexity and infrastructure changes that are part of a sharding implementation. This, in turn, opens the gates for adding "blobs" of data to append to blocks to increase data availability further and allow more processing efficiency. Blobs are big data objects within blocks. These can be utilized to store rollups (Layer 2 solutions) and different kinds of apps requiring big data objects to be stored in an efficient way. This is data off-chain for the validators and requires minimal processing on their part. It reduces the computational load on the network and hence reduces the transaction gas fee. #### ❌ Blobs supported on Hedera? Hedera does not provide blobs under [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844). [HIP-866](https://hips.hedera.com/hip/hip-866) defines how Hedera behaves without blob support. To preserve compatibility and future design space, Hedera will act as if blobs are not being added. This allows existing contracts dependent on blob behavior to function without blobs. Blobs will be prevented from entering the system by prohibiting "Type 3" transactions, which enable blobs. This will keep blobs out of the EVM's concern without affecting other desirable interactions on Hedera. ### Solidity Variables and Opcodes The table below defines the mapping of Solidity variables and operation codes to Hedera. The full list of supported Opcodes for the Cancun hard fork can be found [here](https://www.evm.codes/).
SolidityOpcodeHedera
addressThe address is a mapping of shard.realm.number (0.0.10) into a 20 byte Solidity address. The address can be a Hedera account ID or contract ID in Solidity format.
block.basefeeBASEFEEThe BASEFEE opcode will return zero. Hedera does not use the Fee Market mechanism this is designed to support.
block.chainIdCHAINIDThe CHAINID opcode will return 295(hex 0x0127) for mainnet, 296( hex 0x0128) for testnet, 297( hex 0x0129) for previewnet, and 298 (0x12A) for development networks.
block.coinbaseCOINBASEThe COINBASE operation will return the funding account (Hedera transaction fee collecting account 0.0.98).
block.numberThe index of the record file (not recommended, use block.timestamp).
block.timestampThe transaction consensus timestamp.
block.difficultyAlways zero.
block.gaslimitGASLIMITThe GASLIMIT operation will return the gasLimit of the transaction. The transaction gasLimit will be the lowest of the gas limit requested in the transaction or a global upper gas limit configured for all smart contracts.
msg.senderThe address of the Hedera contract ID or account ID in Solidity format that called this contract. For the root level or for delegate chains that go to the root, it is the account ID paying for the transaction.
msg.valueThe value associated to the transaction associated in tinybar.
tx.originThe account ID paying for the transaction, regardless of depth.
tx.gaspriceFixed (varies with the global fee schedule and exchange rate).

selfdestruct

(address payable recipient)

SELFDESTRUCTAddress will not be reusable due to Hedera’s account numbering policies. On SELFDESTRUCT the contracts HBAR and HTS tokens are transferred to the recipients. If the recipient does not exist or does not have an allowance for any of the HTS tokens, this opcode will fail.
\
.code
Precompile contract addresses will report no code, including HTS System contract.
\
.codehash
Precompile contract addresses will report the empty code hash.
PRNGSEEDThis opcode returns a random number based on the n-3 record running hash.
delegateCallContracts may no longer use delegateCall() to invoke system contracts. Contracts should instead use the call() method.
blobVersionedHashesAtIndexBLOBHASHThe BLOBHASH operation will return all zeros at all times.
blobBaseFeeBLOBBASEFEE

The BLOBBASEFEE operation will return

1 at all times.

Reference: [HIP-866](https://hips.hedera.com/hip/hip-866), [HIP-868](https://hips.hedera.com/hip/hip-868) *** ### Limitation on `fallback()` / `receive()` Functions in Hiero Contracts When developing smart contracts on Hedera, it's important to understand that the `fallback()` and `receive()` functions **do not** get triggered when a contract receives HBAR via a crypto transfer. In Ethereum, these functions act as "catch-all" mechanisms when a contract receives Ether. In Hedera, however, contract balances may change through native HAPI operations, independent of EVM message calls, making it impossible to maintain balance-related invariants with just the `fallback()` or `receive()` methods. #### Impacted Variables * **`msg.sender`:** The address initiating the contract call. * **`msg.value`:** The amount of HBAR sent along with the call. #### Key Points * Developers should implement explicit functions to handle HBAR transfers. * To disable native operations entirely, consider submitting a [Hedera Improvement Proposal (HIP)](https://hips.hedera.com/). Understanding these differences is crucial for anyone developing smart contracts on Hedera, particularly those familiar with Ethereum. *** ## FAQs Yes, you can use Solidity functions directly with the Hedera EVM. However, refer to the [Solidity Variables and Opcodes](#solidity-variables-and-opcodes) table to understand any modifications to opcode descriptions that better reflect their behavior on the Hedera network. Yes, hedera supports jumbo ethereum transactions (HIP-1086), allowing up to **24kb for contract creation** and **128kb for contract calls**. this eliminates the need for uploading bytecode to the file service in most cases. [Learn more](/evm/differences#jumbo-ethereum-transactions). No, jumbo ethereum transactions cannot be included in a `TransactionList` (batch). each jumbo transaction must be submitted individually. Gas covers intrinsic costs (base + per-byte of `callData`) and execution costs (opcodes run by the EVM). Ensure your `gasLimit` and `maxGasAllowance` cover the total. See the [gas and fees page](/evm/development/gas-fees) for details. Hedera does not trigger `fallback()` or `receive()` functions on HBAR transfers. Balances may change through native operations, so use explicit functions to handle HBAR. [Learn more](#limitation-on-fallback-receive-functions-in-hedera-smart-contracts). Yes, but Hardhat cannot set Hedera-native properties like admin key or token associations. For these, use the [Hedera SDK](/native/fundamentals). If your contract relies on blob-related opcodes introduced in the Cancun hard fork, you can still deploy it on Hedera. The blob-related opcodes **will** **not** fail. They'll return default values as [specified by the EVM](https://www.evm.codes/?fork=cancun). Yes, while the Hedera EVM supports the updated opcodes from the Cancun hard fork, you should know the intrinsic gas costs and input data charges specific to Hedera. Refer to the [gas schedule and fees](/evm/development/gas-fees) table for more information. # Forking Hedera Network for Local Testing Source: https://docs.hedera.com/evm/development/forking This guide explains how fork testing works on Hedera, how it differs from traditional EVM chains, and how the [hedera-forking](https://github.com/hashgraph/hedera-forking) library enables local development with Hedera System Contracts. *** ## What is Fork Testing? **Fork Testing** (also known as **Fixtures**) is an Ethereum Development Environment feature that optimizes test execution for smart contracts. It enables: * **Snapshotting blockchain state** - Avoiding recreation of the entire blockchain state for each test * **Using remote state locally** - Any modifications only affect the local (forked) network * **No private key requirements** - Test against remote network state without managing keys * **Debugging tools** - Use `console.log` and other debugging features during testing Popular Ethereum development environments that support fork testing include: * [Foundry](https://book.getfoundry.sh/forge/fork-testing) (using Anvil) * [Hardhat](https://hardhat.org/hardhat-network/docs/overview#mainnet-forking) (using EDR/EthereumJS) *** ## Why is Hedera Different? ### Standard EVM Contracts Work Out-of-the-Box Fork testing works seamlessly for standard EVM smart contracts that don't involve Hedera-specific services. The local test networks provided by development environments are replicas of the Ethereum network. ### Hedera System Contracts Require Emulation Fork testing does not work out-of-the-box for contracts that use Hedera-specific services like: * **Hedera Token Service (HTS)** at address `0x167` * **Exchange Rate** at address `0x168` * **PRNG** at address `0x169` * **Hedera Account Service** at address `0x16a` This is because when the development environment tries to fetch the code at these addresses, the JSON-RPC Relay returns `0xfe` (invalid opcode): ```console theme={null} $ cast code --rpc-url https://mainnet.hashio.io/api 0x0000000000000000000000000000000000000167 0xfe ``` This leads to the error `EvmError: InvalidFEOpcode` when running tests. This is precisely where the hedera-forking library comes in to provide an emulation layer for Hedera System Contracts. For example, with Hardhat, the plugin intercepts JSON-RPC calls to return the appropriate bytecode and state for HTS and for Foundry, the library uses `ffi` to fetch state from the Mirror Node. This is explained in detail below. *** ## How Hedera Forking Works The [hedera-forking](https://github.com/hashgraph/hedera-forking) project provides an emulation layer for Hedera System Contracts written in Solidity. Since it's written in Solidity, it can be executed in any development network environment. ### Architecture Overview The project consists of two main components: 1. **Solidity Contracts** - Provide HTS emulation designed for forked networks 2. **JS Package** - Hooks into JSON-RPC layer to fetch appropriate data when HTS or Hedera Tokens are invoked (used by Hardhat) Both the Foundry library and the Hardhat plugin use the main `HtsSystemContract` implementation. This contract provides the behavior of HTS, but it is state agnostic - meaning the HTS and token state must be provided elsewhere. **Given Foundry and Hardhat provide different capabilities, they differ significantly in how the state is provided to HTS.** *** ## How Token State is Retrieved Foundry and Hardhat use different mechanisms to retrieve token state from the Mirror Node. Understanding these differences is important for troubleshooting and optimizing your fork testing workflow. ### Foundry Library Approach The Foundry library uses a proactive prefetch approach where token state is fetched within Solidity contracts before it's needed. **Key Components:** * `HtsSystemContractJson` - Extends `HtsSystemContract` with JSON data source support * `MirrorNodeFFI` - Fetches data from Mirror Node using Foundry's `ffi` cheatcode **How it works:** 1. When your test calls `Hsc.htsSetup()`, the library deploys `HtsSystemContractJson` at address `0x167` 2. When you access token state (e.g., `balanceOf`), `HtsSystemContractJson` overrides the slot access 3. The contract calls `MirrorNodeFFI` which uses `ffi` to execute `curl` (or PowerShell on Windows) to fetch data from the Mirror Node 4. The fetched data is written to storage using `vm.store` cheatcode (not `sstore`) to avoid `StateChangeDuringStaticCall` errors 5. The data is then returned to your test ```mermaid theme={null} sequenceDiagram autonumber box Local (Foundry) actor user as User Test participant anvil as Anvil (Local Network) participant hts as HtsSystemContractJson
(at 0x167) participant ffi as MirrorNodeFFI
(via ffi/curl) end box Remote participant mirror as Mirror Node end user->>+anvil: address(Token).balanceOf(account) Note over anvil: Token Proxy delegates to 0x167 anvil->>+hts: balanceOf(account) hts->>+ffi: fetchBalance(token, accountNum) ffi->>+mirror: curl: GET /api/v1/tokens/{id}/balances mirror-->>-ffi: { balances: [... ] } ffi-->>-hts: JSON response Note over hts: Parse JSON and store via vm.store hts-->>-anvil: balance value anvil-->>-user: balance value ``` **Why FFI is Required:** * Foundry does not allow creating a JSON-RPC forwarder like Hardhat * However, Foundry allows hooking into internal contract calls via cheatcodes * The `ffi` cheatcode enables executing external commands (like `curl`) from Solidity ### Hardhat Plugin Approach The Hardhat plugin uses a reactive interception approach where a Worker thread intercepts JSON-RPC calls made by Hardhat. **Key Components:** * **JSON-RPC Forwarder** - A Worker thread that intercepts `eth_getCode` and `eth_getStorageAt` calls * **MirrorNodeClient** (JavaScript) - Fetches data from Mirror Node using the `fetch` API **How it works:** 1. When your test runs, Hardhat makes JSON-RPC calls to fetch remote state 2. The Hardhat plugin's Worker intercepts `eth_getCode` and `eth_getStorageAt` calls 3. For `eth_getCode(0x167)`: Returns the compiled `HtsSystemContract` bytecode 4. For `eth_getCode(tokenAddress)`: Returns the HIP-719 Token Proxy bytecode 5. For `eth_getStorageAt(token, slot)`: Uses the storage layout to map the slot to a field, then fetches the value from Mirror Node 6. The fetched data is returned to Hardhat's local network ```mermaid theme={null} sequenceDiagram autonumber box Local (Hardhat) actor user as User Test participant edr as EDR (Local Network) participant plugin as Hardhat Forking Plugin
(JSON-RPC Forwarder) end box Remote participant mirror as Mirror Node end user->>+edr: address(Token).totalSupply() edr->>+plugin: eth_getCode(Token) plugin->>+mirror: GET /api/v1/tokens/{tokenId} mirror-->>-plugin: Token {} plugin-->>-edr: HIP-719 Token Proxy bytecode
(delegate calls to 0x167) edr->>+plugin: eth_getCode(0x167) plugin-->>-edr: HtsSystemContract bytecode edr->>+plugin: eth_getStorageAt(Token, slot) Note over plugin: Map slot to field using storage layout plugin->>+mirror: GET /api/v1/tokens/{tokenId} mirror-->>-plugin: Token{} plugin-->>-edr: Token{}. totalSupply edr-->>-user: Token{}.totalSupply ``` **Why a Worker Thread is Required:** * Hardhat does not allow hooking into internal contract calls (see [issue #56](https://github.com/hashgraph/hedera-forking/issues/56)) * The plugin must intercept at the JSON-RPC level before Hardhat processes the requests * The Worker thread runs asynchronously to handle the interception ### Comparison: Foundry vs Hardhat Approaches | Aspect | Foundry Library | Hardhat Plugin | | ------------------ | -------------------------------------- | --------------------------------------- | | **State Fetching** | Proactive (prefetch in Solidity) | Reactive (intercept JSON-RPC) | | **Data Fetcher** | `MirrorNodeFFI` (Solidity + curl) | `MirrorNodeClient` (JavaScript + fetch) | | **Hook Point** | Internal contract calls via cheatcodes | JSON-RPC layer via Worker thread | | **Requirement** | `ffi = true` in foundry. toml | `chainId` and `workerPort` in config | | **OS Dependency** | curl (Unix) or PowerShell (Windows) | Node.js fetch API | | **Storage Writes** | `vm.store` cheatcode | Returned via JSON-RPC response | *** ## HTS Supported Methods The emulation layer supports a subset of HTS functionality. Refer to [https://github.com/hashgraph/hedera-forking#hedera-token-service-supported-methods](https://github.com/hashgraph/hedera-forking#hedera-token-service-supported-methods) for the latest list. *** ## Limitations and Important Notes The HTS emulation contract **SHOULD ONLY** be used to ease development workflow when working with Hedera Tokens. The HTS emulation contract **DOES NOT** replicate Hedera Token Services fully. Behavior might differ when switching from local development to a real Hedera network. **Always test your contracts against a real Hedera network before launching your contracts.** ### Key Limitations 1. **Behavior differences** - Some edge cases may behave differently in emulation vs. the real Hedera network. 2. **Block number considerations** - When forking from a specific block, ensure your deployed contracts exist at that block number. 3. **Rate limiting** - When running many tests (especially fuzz tests), you may hit RPC rate limits. Consider lowering fuzz run counts. 4. **Storage layout constraints** - Solidity `mapping`s compute storage slots that are not reversible, which required special handling in the emulation layer. 5. **Foundry `ffi` requirement** - The Foundry library requires `ffi = true` which allows executing external commands. This is necessary for `curl` calls to the Mirror Node. 6. **Hardhat async limitations** - The Hardhat plugin requires manual configuration of `chainId` and `workerPort` because Hardhat plugin loading is synchronous. *** ## Development Framework Support ### Foundry The Foundry library uses `ffi` (Foreign Function Interface) to fetch remote state from the Mirror Node using `curl` (or PowerShell on Windows). **Key setup:** * Enable `ffi = true` in `foundry.toml` * Call `Hsc.htsSetup()` in your test setup **How it fetches data:** ```solidity theme={null} import {Hsc} from "hedera-forking/Hsc.sol"; function setUp() public { Hsc.htsSetup(); // Deploys HtsSystemContractJson at 0x167 } ``` When you access token state, the library: 1. Intercepts the storage slot access 2. Uses `MirrorNodeFFI` to call `curl` via `ffi` 3. Parses the JSON response 4. Writes data using `vm.store` cheatcode ### Hardhat The Hardhat plugin intercepts JSON-RPC calls (`eth_getCode` and `eth_getStorageAt`) to provide HTS emulation. **Key setup:** * Install `@hashgraph/system-contracts-forking` * Import the plugin in `hardhat.config.ts` * Configure `chainId` and `workerPort` in forking config **Configuration example:** ```typescript theme={null} import "@hashgraph/system-contracts-forking/plugin"; // In your hardhat.config.ts hardhat: { forking: { url: "https://mainnet.hashio.io/api", blockNumber: 70531900, // @ts-ignore - custom properties for hedera-forking plugin chainId: 295, // Required: 295 (mainnet), 296 (testnet), 297 (previewnet) // @ts-ignore workerPort: 1235 // Required: Any free port } } ``` *** ## Learn How to Fork the Hedera Network for Local Testing *** ## Further Resources * [hedera-forking GitHub Repository](https://github.com/hashgraph/hedera-forking) * [Internals Documentation](https://github.com/hashgraph/hedera-forking/blob/main/INTERNALS.md) * [FAQ](https://github.com/hashgraph/hedera-forking/blob/main/FAQ.md) * [HIP-719: Token Proxy Contract](https://hips.hedera.com/hip/hip-719) * [Foundry Fork Testing Documentation](https://book.getfoundry.sh/forge/fork-testing) * [Hardhat Mainnet Forking Documentation](https://hardhat.org/hardhat-network/docs/overview#mainnet-forking) [GitHub](https://github.com/kpachhai) | [LinkedIn](https://www.linkedin.com/in/kiranpachhai/) # Gas and Fees Source: https://docs.hedera.com/evm/development/gas-fees Understanding gas costs, throttling, and fee calculation for Hiero Contracts ## Gas When executing smart contracts, the **EVM** requires the amount of work paid in **gas**. The "work" includes computation, state transitions, and storage. Gas is the unit of measurement used to charge a fee per opcode executed by the EVM. Each opcode has a defined gas cost. Gas reflects the cost necessary to pay for the computational resources used to process transactions. Following **[HIP-1249](https://hips.hedera.com/hip/hip-1249)**, Hedera has implemented **operational-based throttling** and eliminated **minimum gas charges**, providing more predictable resource management and fairer billing for smart contract operations. ## Weibar Gas information for EVM operations is returned in **weibar** (introduced in [HIP-410](https://hips.hedera.com/hip/hip-410)). * `1 weibar = 10^-18 HBAR` * `1 tinybar = 10^10 weibar` As noted in [HIP-410](https://hips.hedera.com/hip/hip-410), this maximizes compatibility with third-party tools that expect ether units to be operated on in fractions of `10^18`, also known as a **Wei**. ## Gas Schedule and Fee Calculation Gas charges apply to `ContractCall`, `ContractCreate`, and `EthereumTransaction`. Other smart contract-related transactions (e.g., `ContractDelete`, `ContractGetInfo`) use the standard [Fee Model](/learn/core-concepts/fee-model), a base fee plus extras for node, network, and service components, paid in HBAR. For gas-consuming transactions (`ContractCall`, `ContractCreate`, `EthereumTransaction`), gas is an "extra" in the service fee component. The gas extra covers EVM execution costs. All other fee components (node fee, network fee, and the non-gas portion of the service fee) follow the base-fee-plus-extras model. Gas fees for EVM transactions consist of: * **Intrinsic Gas**: The minimum amount of gas required to execute a transaction * **EVM Opcode Gas**: The gas required to execute the defined opcodes for the smart contract call * **Hedera System Contract Gas**: The required gas associated with Hedera-defined transactions, such as using the Hedera Token Service system contract **High-volume contract creation.** `ContractCreateTransaction` supports the `high_volume` flag ([HIP-1313](https://hips.hedera.com/hip/hip-1313)), which routes the transaction through dedicated high-volume throttle capacity with variable-rate pricing. This applies to **HAPI-based contract creation only** — contract deployments via EVM `CREATE` / `CREATE2` opcodes are not included. See the [High-Volume Entity Creation](/learn/core-concepts/high-volume-entity-creation) guide for details. ### Intrinsic Gas A transaction submitted to the smart contract service must be sent with enough gas to cover **intrinsic gas**. With the **Cancun fork** of the EVM update, intrinsic gas is calculated as: ```bash theme={null} 21000 + 4 × (number of zero bytes) + 16 × (number of non-zero bytes) = intrinsic gas ``` * **21,000**: The base gas cost for any transaction * **4 × (zero bytes)**: The cost of each zero byte in the transaction payload * **16 × (non-zero bytes)**: The cost for each non-zero byte in the transaction payload If insufficient gas is submitted, the transaction will **fail during precheck** and no record will be created. This applies to both standard transactions and **jumbo EthereumTransactions** introduced by **[HIP-1086](https://hips.hedera.com/hip/hip-1086)**, which allow larger `callData` payloads. ### EVM Opcode Gas Execution costs in the EVM include both **fixed** and **dynamic** costs: * **Fixed Cost**: Base cost per opcode execution * **Dynamic Cost**: Varies by parameters (e.g., cold vs warm storage access) **Example**: For the `SLOAD` opcode, which loads data from storage: * **Fixed Cost**: `100 gas` units (base cost per execution) * **Dynamic Cost (Cold Access)**: `2,100 gas` units (first-time access to the storage slot) * **Dynamic Cost (Warm Access)**: `100 gas` units (subsequent access within the transaction) If `SLOAD` accesses a storage slot twice within the same transaction, the total gas cost would be calculated as follows: * **First Access (Cold)** = `100 + 2,100 = 2,200 gas` * **Second Access (Warm)** = `100 + 100 = 200 gas` * **Final Gas Cost Total** = `2,400 gas` 📣 *Explore [opcodes in Cancun fork](https://www.evm.codes/).* ### Hedera System Contract Gas Hedera system contract gas fees apply only when using a native Hedera service. They are calculated by converting the transaction cost in **USD** to gas using a set conversion rate, then adding a **20% surcharge** for overhead and variations in gas usage. **Example**: For a **\$0.10 transaction** with a conversion rate of `1,000,000 gas per USD`: * **Base Gas Cost** = `0.10 × 1,000,000 = 100,000 gas` * **Total Gas Cost** = `100,000 × 1.2 = 120,000 gas` * **Final gas cost total** = `120,000 gas` Following **[HIP-1249](https://hips.hedera.com/hip/hip-1249)**, system contract operations also contribute to **operational throttling** through measured ops costs, providing layered resource protection alongside gas-based billing. #### System Contract View Functions The gas requirements for **HTS view functions** can be calculated in a slightly modified manner. The transaction type of `getTokenInfo` can be used and a nominal price need not be calculated. This implies that converting the fee into HBAR is not necessary as the canonical price (`$0.0001`) can be directly converted into gas by using the conversion factor of **852 tinycents**. Add **20% markup**. Thus gas cost is: * **Base gas cost** = `(1000000 + 852000 - 1) × 1000 / 852000 = 2173 gas` * **Total Gas Cost** = `2173 × 1.2 = 2607 gas` **Final gas cost total** = `2607 gas` **Example System Contracts:** * **[Hedera Token Service (HTS)](https://github.com/hiero-ledger/hiero-contracts/blob/main/contracts/token-service/HederaTokenService.sol)** * **[Pseudo Random Number Generator (PRNG)](https://github.com/hiero-ledger/hiero-contracts/blob/main/contracts/prng/PrngSystemContract.sol)** * **[Exchange Rate](https://github.com/hiero-ledger/hiero-contracts/blob/main/contracts/exchange-rate/ExchangeRateSystemContract.sol)** **Learn More**: Our detailed gas calculation [reference](https://github.com/hashgraph/hedera-services/blob/develop/hedera-node/docs/design/services/smart-contract-service/system-contract-gas-calc.md#system-contracts) explains the precise steps for calculating gas fees on Hedera. ## Gas for Jumbo Transactions **Jumbo EthereumTransactions** that include large `callData` under **[HIP-1086](https://hips.hedera.com/hip/hip-1086)** follow the same gas model as standard EVM transactions. This gas pricing applies only to [EthereumTransaction](/native/smart-contracts/ethereum-transaction) type; standard HAPI transactions are unaffected. ### Formula The gas cost for `callData` is based on byte content: ``` callData gas = (4 × zero bytes) + (16 × non-zero bytes) ``` This is added to the base gas and execution gas to calculate the total gas required. *📣 [Learn more about Ethereum jumbo transactions](/native/smart-contracts/ethereum-transaction#handling-large-calldata-payloads)* ### Example Calculation For **100KB of `callData`** with `10,000 zero bytes` and `90,000 non-zero bytes`: * **Zero byte gas**: `4 × 10,000 = 40,000` * **Non-zero byte gas**: `16 × 90,000 = 1,440,000` * **Total callData gas** = `1,480,000` Ensure both `gasLimit` (RLP) and `maxGasAllowance` (wrapper) are set high enough to cover the total. 🔹 **Size Caps**: Jumbo EthereumTransactions are capped at **24KB** (creation) and **128KB** (call). Larger payloads require `callDataFileId`.\ 🔹 **Throttling**: Jumbo transactions are subject to dedicated **operational throttling** based on transaction type and complexity. ## Gas Limit The **gas limit** is the maximum amount of gas you are willing to pay for an operation. The current opcode gas fees are reflective as of the **[0.22 Hedera Service release](/networks/release-notes/services#v0.22)**. | Operation | Cancun Cost (Gas) | Current Hedera (Gas) | | ------------------------------------------------------------------------- | ---------------------------------------------- | ---------------------------------------------- | | Code deposit | 200 \* bytes | 200 \* bytes | |

BALANCE
(cold account)

| 2600 | 2600 | |

BALANCE
(warm account)

| 100 | 100 | | `EXP` | 10 + 50/byte | 10 + 50/byte | |

EXTCODECOPY
(cold account)

| 2600 + Mem | 2600 + Mem | |

EXTCODECOPY
(warm account)

| 100 + Mem | 100 + Mem | |

EXTCODEHASH
(cold account)

| 2600 | 2600 | |

EXTCODEHASH
(warm account)

| 100 | 100 | |

EXTCODESIZE
(cold account)

| 2600 | 2600 | |

EXTCODESIZE
(warm account)

| 100 | 100 | |

LOG0, LOG1, LOG2,
LOG3, LOG4

|

375 + 375\*topics
+ data Mem

|

375 + 375\*topics
+ data Mem

| |

SLOAD
(cold slot)

| 2100 | 2100 | |

SLOAD
(warm slot)

| 100 | 100 | |

SSTORE
(new slot)

| 22,100 | 22,100 | |

SSTORE
(existing slot,
cold access)

| 2,900 | 2,900 | |

SSTORE
(existing slot,
warm access)

| 100 | 100 | |

SSTORE
refund

| As specified by the EVM | As specified by the EVM | |

CALL et al.
(cold recipient)

| 2,600 | 2,600 | |

CALL et al.
(warm recipient)

| 100 | 100 | |

CALL et al.
HBAR/ETH Transfer Surcharge

| 9,000 | 9,000 | |

SELFDESTRUCT
(cold beneficiary)

| 2600 | 2600 | |

SELFDESTRUCT
(warm beneficiary)

| 0 | 0 | | `TSTORE` | 100 | 100 | | `TLOAD` | 100 | 100 | | `MCOPY` | 3 + 3\*words\_copied + memory\_expansion\_cost | 3 + 3\*words\_copied + memory\_expansion\_cost | The terms **'warm'** and **'cold'** in the above table correspond with whether the account or storage slot has been read or written to within the current smart contract transaction, even within a child call frame. **'CALL et al.'** includes with limitation: `CALL`, `CALLCODE`, `DELEGATECALL`, and `STATICCALL` Reference: [HIP-206](https://hips.hedera.com/hip/hip-206), [HIP-865](https://hips.hedera.com/hip/hip-865) ## Operational-Based Throttling While most **EVM-compatible networks** use per-block gas limits for resource control, Hedera uses **time-based throttling**. Following **[HIP-1249](https://hips.hedera.com/hip/hip-1249)**, Hedera has transitioned from **gas-per-second** to **operations-per-second (ops/sec) throttling**, controlling network throughput based on actual computational demands rather than gas estimates. This potentially supports **significantly higher throughput** while maintaining EVM compatibility. **Ops costs** are derived from **nanosecond performance benchmarks** with safety margins, covering **EVM opcodes**, **precompiles**, and **system contracts**. Gas continues for user billing and per-transaction limits, separating cost calculation from throttling. **Performance**: Real-world testing shows substantial improvements, with **Uniswap** achieving over **150 million gas/sec** compared to the previous **15 million gas/sec** limit. ### Transaction Execution Outcomes With **operational-based throttling**, transaction processing follows specific patterns based on resource availability: **Ops Throttle Exhausted**: When the operations-per-second throttle is exhausted either before execution begins or during execution, transactions fail with a `THROTTLED_AT_CONSENSUS` error and are charged only the **[intrinsic gas fee](/evm/development/gas-fees#intrinsic-gas)**. **Gas Limit Exhausted**: If a transaction's gas limit is exhausted before the ops throttle, it fails with an **out-of-gas error** and users are charged for the full gas used, with ops deducted for work completed. **Successful Execution**: For successful transactions, users are charged for the **exact gas used** and the corresponding ops units are deducted from the throttle bucket. ## Gas Reservation and Unused Gas Refund Hedera throttles transactions **before consensus**, and nodes limit the number of transactions they can submit to the network. At **consensus time**, if the maximum number of transactions is exceeded, the excess transactions are not evaluated and are canceled with a **busy state**. Throttling by variable gas amounts provides challenges to this system, where the nodes only submit a share of their transaction limit. To address this, Hedera now uses **operational-based throttling** that applies only at **consensus**. The system operates with: * **Frontend (ingest/precheck)**: Uses **TPS limits** only with no gas-based throttling * **Backend (consensus)**: Applies **operations-per-second (ops) throttling** based on actual computational work performed It is impossible to know the actual evaluated gas pre-consensus because the network state can directly impact the flow of the transaction, which is why pre-consensus uses the `gasLimit` field and will be referred to as the **gas reservation**. **Contract query requests** are unique and bypass the consensus stage altogether. These requests are executed solely on the local node that receives them and only influence that specific node's precheck throttle. To ensure transactions can execute properly, setting a **higher gas reservation** than will be used by execution is common. On **Ethereum mainnet**, the entire reservation is charged to the account before execution, and the unused portion is credited back. However, Ethereum utilizes a **[memory pool (mempool)](/support/glossary#mempool)** and does transaction ordering at block production time, allowing the block limit to be based only on used and not reserved gas. Users are charged only for the **actual gas used** during transaction execution, with **unused gas being fully refunded**. This aligns with Ethereum's billing model and eliminates the previous minimum charge requirements. ## Maximum Gas Per Transaction Each transaction on Hedera is capped by a **per-transaction gas limit**. If a transaction's `gasLimit` exceeds this cap, it is rejected during precheck with the `INDIVIDUAL_TX_GAS_LIMIT_EXCEEDED` error and does not proceed to consensus. This gas metering approach ensures efficient resource use, preventing excessive consumption while allowing flexibility for larger, more complex smart contracts. Per-transaction gas limits remain unchanged (e.g., **15 million gas per transaction**), while network throughput is now managed through **operational-based throttling**. Refer to [HIP‑1249](https://hips.hedera.com/hip/hip-1249) for implementation details. **Reference**: [HIP-185](https://hips.hedera.com/hip/hip-185) # JSON-RPC Relay Source: https://docs.hedera.com/evm/development/json-rpc/index The [Hiero JSON-RPC Relay](https://github.com/hiero-ledger/hiero-json-rpc-relay) is an open-source project implementing the EVM JSON-RPC standard. It allows developers to interact with Hedera nodes using familiar EVM tools, allowing developers and users to deploy, query, and execute contracts as they usually would. Check out the interactive[ OpenRPC Specification](https://playground.open-rpc.org/?schemaUrl=https://raw.githubusercontent.com/hashgraph/hedera-json-rpc-relay/main/docs/openrpc.json\&uiSchema%5BappBar%5D%5Bui:splitView%5D=false\&uiSchema%5BappBar%5D%5Bui:input%5D=false\&uiSchema%5BappBar%5D%5Bui:examplesDropdown%5D=false) and a simple [list of endpoints](https://github.com/hiero-ledger/hiero-json-rpc-relay/blob/main/docs/rpc-api.md). ## HBAR decimal places The Hiero JSON RPC Relay **`msg.value`** uses `18 decimals` when it returns HBAR. As a result, the **`gasPrice`** value returns 18 decimal places since it is only utilized from the JSON RPC Relay. Refer to the [HBAR page](/native/fundamentals/hbars) for a list of Hiero APIs and the decimal places they return. ## JSON RPC Relay Options for the Hedera Network When interacting with smart contracts on Hedera, developers have several options for setting up a JSON RPC Relay. Each choice comes with unique advantages and trade-offs based on your project's needs, scalability, and operational preferences. 1. [**Hiero Local Node**](https://github.com/hiero-ledger/hiero-local-node)**:** It provides a built-in JSON RPC Relay and simulates the Hedera network environment locally. This option is ideal for quick prototyping, debugging, and isolated testing without external dependencies. It's ideal if you want to run extensive and repeated tests without having to worry about running out of testnet HBAR. 2. [**Self-hosted JSON RPC Relay**](https://github.com/hiero-ledger/hiero-json-rpc-relay/tree/main)**:** Running your own JSON RPC Relay offers complete control over configurations and network selection (testnet, previewnet, mainnet). It is best suited for projects requiring flexibility, high reliability, and scalability, especially in production environments. 3. [**Third-party JSON RPC Relay Services**](#community-hosted-json-rpc-relays)**:** Several third-party providers offer managed JSON RPC Relay services with different levels of reliability, service-level agreements (SLAs), and fee structures. These services remove infrastructure maintenance overhead, allowing teams to focus more on development (*you can find the list of supported services* [*below*](#community-hosted-json-rpc-relays)*).* | Feature | Hiero Local Node | Self-hosted RPC Relay | Third-party RPC Relay | | ----------------------------- | :-------------------: | :-------------------: | :------------------------------------------: | | **Infrastructure Management** | Minimal | Required | None | | **Reliability and Stability** | High (local) | High | Variable by SLA | | **Scalability** | / (local) | Flexible | Variable by provider | | **Setup Complexity** | Low to Medium | Medium to High | Low | | **Ideal Use Case** | Testing & Development | Testing & Production | Builders who prefer convenience & Production | Read the [**JSON RPC Relay Comparison blog**](https://hedera.com/blog/selecting-a-json-rpc-relay-for-your-project) post to learn more about the different options! ## Community Hosted JSON-RPC Relays Anyone in the community can set up their own JSON RPC relay that applications can use to deploy, query, and execute smart contracts. The list of community-hosted Hiero JSON RPC relays and endpoints for previewnet, testnet, and mainnet can be found in the table below, as well as their associated docs or websites. #### JSON-RPC Relay Endpoints
NetworkChain IDHashio RPC URLthirdweb RPC URL
Mainnet295[https://mainnet.hashio.io/api](https://mainnet.hashio.io/api)[https://295.rpc.thirdweb.com](https://295.rpc.thirdweb.com)
Testnet296[https://testnet.hashio.io/api](https://testnet.hashio.io/api)[https://296.rpc.thirdweb.com](https://296.rpc.thirdweb.com)
Previewnet297[https://previewnet.hashio.io/api](https://previewnet.hashio.io/api)\*\*[https://297.rpc.thirdweb.com](https://297.rpc.thirdweb.com)
### 🚨 **PLEASE NOTE** **Hashio** is for development and **testing purposes only**. Production use cases are strongly encouraged to use [commercial-grade JSON-RPC relays](#community-hosted-json-rpc-relays) or host their own instance of the [Hiero JSON-RPC Relay](https://github.com/hiero-ledger/hiero-json-rpc-relay). ### **Note** If you want to add your hosted JSON-RPC relay to this list, please open an issue in the [Hedera docs GitHub repository](https://github.com/hashgraph/hedera-docs). Please visit the community-hosted websites to review any limitations specific to their instance. ## FAQ * [**Hashio**](https://www.hashgraph.com/hashio/) * [**Arkhia**](https://www.arkhia.io/features/#api-services) * [**Validation Cloud**](https://docs.validationcloud.io/about/hedera/json-rpc-relay-api) * [**QuickNode**](https://www.quicknode.com/docs/hedera) * [**Hgraph**](https://docs.hgraph.com/category/json-rpc) The configuration guide to connect to the Hedera Network over RPC can be found [here](/evm/tutorials/intermediate/json-rpc-connections). The endpoints for previewnet, testnet, and mainnet can be found on [Hashio](https://www.hashgraph.com/hashio/), accessible through the [Hashgraph](https://www.hashgraph.com) website. The JSON-RPC Relay `msg.value` uses 18 decimals when it returns HBAR. The `gasPrice` value also returns 18 decimal places. *Check out the* [*HBAR page*](/native/fundamentals/hbars) *for the full list of Hedera APIs and their decimal representation.* To contribute or log errors, please refer to the [Contributing Guide](/support/contributing) and submit them as issues in the [GitHub repository](https://github.com/hiero-ledger/hiero-json-rpc-relay). # Smart Contract Rent Source: https://docs.hedera.com/evm/development/rent 🚨 **HEDERA COUNCIL HAS NOT ENABLED RENTS ON SMART CONTRACTS YET. RENTS PAY FOR THE ONGOING USAGE OF RESOURCES USED BY THE SMART CONTRACT. HEDERA INTENDS TO ENABLE THE RENTS IN THE FUTURE, AS DESCRIBED IN THIS SECTION. MORE DETAILS COMING SOON... 🚨** Smart contract rent is a recurring payment mechanism designed to maintain resource allocation and is required for contracts to remain active on the network. For contracts, rent is comprised of two primary components: **➡** [**Auto-Renewal**](#contract-auto-renewal) **➡** [**Storage Payments**](#storage-payment) *** ## Contract Auto-Renewal Auto-renewal is a feature that automatically renews the life of non-deleted smart contracts by a minimum of 90 days. Contract authors are encouraged to establish an auto-renew account specifically for this purpose. The network will attempt to automatically charge the **renewal payment** to the expired contract's auto-renew account. The network will attempt to charge the contract if an auto-renew account has zero balance. If the account lacks sufficient funds for renewal, the contract goes into a one-week grace period. During this time, the contract is inoperable unless funds are added, its expiry is extended (via `ContractUpdate`), or it receives HBAR. Failing to renew will result in the contract being purged from the state. *** ## Storage Payments Contract storage payments on Hedera will activate once **100 million key-value pairs** are stored cumulatively across the network. The Hedera Coin Economics Committee is expected to set a rate of **\$0.02 per key-value pair per year**. This applies to all contracts on Hedera, regardless of the contract being created before or after the rent payments go live. Once storage payments are enabled on Hedera, each contract has **100 free key-value pairs** of storage available. Then, once a contract exceeds the first 100 free key-value pairs, it must pay storage fees. > *Storage fees will be part of the rent payment collected when a contract is auto-renewed. Valid renewal windows are between \~30 and \~92 days (see* [*HIP-372*](https://hips.hedera.com/hip/hip-372)*).* If a high enough utilization threshold is reached, **congestion pricing applies.** In this case, prices charged will be inversely proportional to the remaining system capacity of the network (lower remaining capacity means higher pricing). This applies to all transactions. *** ## Smart Contract Rent - Frequently Asked Questions (FAQ) Distributed networks like Hedera have a finite amount of computational resources. When entities like smart contracts are deployed on a decentralized network, a portion of those resources are consumed. Thus, it is unfeasible to maintain an unlimited number of entities for an infinite amount of time on finite resources. Solving this problem is necessary, and it’s a key topic of discussion by Leemon and [others](https://www.coindesk.com/markets/2018/03/27/vitalik-wants-you-to-pay-to-slow-ethereums-growth/) in the layer 1 network space. Contract rent is an economically and technically viable approach to manage smart contract entities and state storage. All other network entities (e.g., Tokens, accounts, topics, and files) will also pay rent. However, the timeline for the rent is not yet defined. Sufficient time and notice will be provided to the community before enabling rent for other entities. Rent is defined as the recurring payment required for contracts (and, eventually, all other Hedera entities) to remain active on the network. For contracts, rent is comprised of **auto-renewal** and **storage** payments: * **Auto-renewal payments** The auto-renewal fee for a contract is \$0.026 USD per 90 days. * **Storage payments** will start once a total of **100 million key-value pairs** are stored cumulatively across the network. These storage fees will be part of the rent payment collected when a contract is auto-renewed. The storage fee rate is \$0.02 per key-value pair per year. Every entity on Hedera has the fields `expirationTime`, `autorenewPeriod`, and `autorenewAccount`. 1. When the `expirationTime` for a contract is reached, the network will first try to charge rent to the contract’s `autoRenewAccount` * If renewal is successful, then the contract remains active on the network * If renewal fails, then the contract is marked as `expired` 2. An `expired` entity is given a grace period before it is removed from the network. During the grace period, the entity (contract) is inactive, and all transactions involving it will fail, except for an update transaction to extend the `expirationTime` * A contract in the grace period can be immediately "re-activated" by either sending it some HBAR or manually extending its `expirationTime` via a contract update transaction 3. At the end of the grace period, the contract is permanently removed from the ledger if: * The contract and its `autoRenewAccount` still have a zero HBAR balance at the end of the grace period, OR * The contract is not manually extended during the grace period Note that the ID number of a removed entity is not reused going forward. In addition, if an entity was marked as `deleted`, then it cannot have its `expirationTime` extended. Neither an update transaction nor an auto-renew will be able to extend it. See the diagram below and [HIP-16](https://hips.hedera.com/hip/hip-16) for more details. The grace period between entity expiration and deletion is 30 days. Smart contracts on Hedera can pay for rent in two ways: external funds or contract funds. When the `expirationTime` for a contract is reached, the network will first try to charge rent to the contract’s `autoRenewAccount`: * If the `autoRenewAccount` has sufficient HBAR to pay for the `autoRenewPeriod`, then the contract is successfully renewed * If the `autoRenewAccount` has some HBAR but not enough to afford the full `autoRenewPeriod`, then the contract is extended for as long as possible (say, 1 week instead of 90 days). Once that extension (1 week) elapses, if the `autoRenewAccount` hasn't been re-funded to cover the `autoRenewPeriod`, then the contract account itself will be charged for rent * If the `autoRenewAccount` has a zero HBAR balance, then the contract itself is charged * If the `autoRenewAccount` and the contract both have a zero HBAR balance at the time that renewal fees are due, the contract is marked as `expired` Calling an `expired` contract will resolve to `CONTRACT_EXPIRED_AND_AWAITING_REMOVAL`. If an expired contract that holds native Hedera Token Service (HTS) tokens reaches the deletion stage, then the assets held by that contract are returned to their respective treasury accounts. If the deleted contract is being used as a specific key for an HTS token, then that key field will refer to a contract that no longer exists. That specific key can be changed, as long as an admin key was specified during token creation. If the token is immutable (no admin key), the specific key cannot be changed. Contracts that are the treasury for HTS tokens do not expire at this moment (subject to change in the future). The minimum renewal period possible is 2,592,000 seconds (\~30 days) and the maximum is 8,000,001 seconds (\~92 days). See details in [HIP-372: Entity Auto-Renewals and Expiry Window](https://hips.hedera.com/hip/hip-372). The cost of rent scales just about linearly with the length of the renewal period. So a renewal that pays for 90 days will cost \~3 times as much as a renewal that pays for 30 days. Mirror nodes provide the expiration time for contracts. You can obtain this information using the mirror node REST API (show it as `expiration_time`) and network explorers like HashScan (shows it as `Expires at`). According to [HIP-16: Entity Auto-Renewal](https://hips.hedera.com/hip/hip-16), records of auto-renew charges will appear as `actions` in the record stream, and will be available via mirror nodes. In addition, the fee breakdown is provided in network explorers like HashScan for the contract update transaction. No receipts or records for auto-renewal actions will be available via HAPI queries. [HIP-449](https://hips.hedera.com/hip/hip-449) provides technical details on how information for expiring contracts is included in the record stream. Yes, that is possible for contracts. * Storage payments for contracts will only start being charged once **100 million key-value pairs** are reached cumulatively across the network * After than, each contract has **100 free key-value pairs** of storage available. Once a contract exceeds the first 100 free key-value pairs, it must pay storage fees Contracts created via `CREATE2` inside the EVM will inherit the `autorenewaccount` and `autorenewPeriod`of the `sender` address. For example, if you call contract `0xab...cd` which has `autorenewAccount` `0.0.X` and `autorenewPeriod` of 45 days, and this contract deploys a new contract `0xcd...ef`, then the new contract will also have `autorenewAccount` `0.0.X`and `autorenewPeriod` of 45 days. Also, remember that rent can be covered by the HBAR balance of a contract. Thus, developers can send HBAR to the contract or configure the contract to charge users a specific HBAR amount when executing operations. # Smart Contract Security Source: https://docs.hedera.com/evm/development/security The [Hedera Smart Contract Service (HSCS)](/support/glossary#hedera-smart-contract-service-hscs) integrates the features of Hedera's third-generation native entity functionality—high throughput, fast finality, predictable and affordable fees, and fair transaction ordering—with a highly optimized and performant second-generation [Ethereum Virtual Machine (EVM)](/support/glossary#ethereum-virtual-machine-evm). We aim to offer comprehensive support for smart contracts originally written for other EVM-compatible chains and to enable their seamless deployment on Hedera. *** ## EVM Equivalence We strive to ensure that developers can conveniently point to a Hedera-supported RPC endpoint and perform smart contract executions and queries using the same code and similar tools to achieve EVM equivalence. All smart contract transactions are executed using the [Besu EVM](/support/glossary#hyperledger-besu-evm) to realize this objective, and the resulting changes are stored in the Hedera-optimized [Virtual Merkle Tree](/support/glossary#virtual-merkle-tree) state. Users are thus guaranteed deterministic finality (as opposed to probabilistic finality) of smart contract executions within 2-3 seconds while ensuring that state changes are entirely encompassed within smart contract functionality. 🔔 A Comprehensive breakdown of Hedera's EVM equivalence goals and exceptions can be found [**here**](/evm/differences). *** ## Security Model ### Old model (v1) boundaries The old security model (pre [0.35.2](https://github.com/hashgraph/hedera-services/releases/tag/v0.35.2)) supported account key signatures provided at transaction time for authorization. Some of the key characteristics of this model included: * [Smart contracts](/support/glossary#smart-contract) could only change their own storage or the storage they were [delegate called](https://docs.soliditylang.org/en/v0.8.19/introduction-to-smart-contracts.html#delegatecall-and-libraries) with. * System smart contracts could be delegate called to carry out [Hedera Token Service (HTS)](/support/glossary#hedera-token-service-hts) operations on behalf of another account - Externally Owned Account (EOA) or contract account. * Smart Contracts could change an EOA’s storage with the appropriate signature in the transaction. * Smart Contracts could change an EOA’s balance with the appropriate signature in the transaction or with prior addition to an allowance approval list. This greatly improved user experience as contracts could combine transactions in an attempt at atomicity. For instance, a contract could associate, transfer and approve transactions on a user's behalf with one signature. While focusing on usability, this approach did not address cases in which bad actors could carry out an unsanctioned transaction on behalf of a user, e.g., [https://hedera.com/blog/analysis-remediation-of-the-precompile-attack-on-the-hedera-network](https://hedera.com/blog/analysis-remediation-of-the-precompile-attack-on-the-hedera-network) To address this, the core Hedera engineers thoroughly analyzed the Smart Contract Service and the HTS system contracts, aiming to secure the state and token assets of users and the network during Smart Contract executions. The results of this effort are the guidelines in [Consensus Node release v0.35.2](https://github.com/hashgraph/hedera-services/releases/tag/v0.35.2). ### New model (v2) boundaries In the new security model, account key signatures cannot provide authorization for contract actions. Its key characteristics include: * Smart contracts can only change their own storage or the storage they were [delegate called](https://docs.soliditylang.org/en/v0.8.19/introduction-to-smart-contracts.html#delegatecall-and-libraries) with. * System smart contracts may **not** be delegate called, except from the Token proxy/facade flow, e.g., [HIP 719](https://hips.hedera.com/hip/hip-719). In such cases, HTS tokens are represented as smart contracts (see [HIP 218](https://hips.hedera.com/hip/hip-218)) for common ERC methods. * Smart contracts can change an EOAs storage only if the contract ID is contained in the EOAs key. * Smart contracts can change an EOAs balance if approved for a token allowance for a specific token held by the EOA. #### Boundary comparison table
Boundary Specv1 Modelv2 ModelChange
Storage ChangesSmart Contracts could only change their own storage or the storage they were delegate called withSmart contracts can only change their own storage or the storage they were delegate called withN
System Contract Call TypesSystem smart contracts could be delegate called in order to carry out Hedera Token Service operations on behalf of another account (EOA) or contract.System smart contracts may not be delegate called, except from the Token facade flow, which presents HTS tokens as smart contracts for common ERC methods.Y
Permissioned Account Storage ChangesSmart Contracts could change an EOA’s storage with the appropriate signature in the transaction.Smart contracts can change an EOAs storage if the contract ID is contained in the EOAs key.Y
Permissioned Account Balance ChangesSmart Contracts could change an accounts (EOA or contract) balance with the appropriate signature in the transaction or with prior addition to an allowance approval listSmart contracts can change an EOAs balance if they have been approved a token allowance.Y
In summary, HSCS utilizes a three-level security approach: 1. **Level 0 - EVM Security Model:** Entities may only modify their own state and balance. 2. **Level 1 - ERC Account Value Security Models:** Transfer and access to account value will follow tested web3 interface standards, e.g., ERC20, ERC721. 3. **Level 2 - Hedera Advanced Security Features:** Unique Hedera features may utilize contract-compatible permissions, e.g., ContractID keys. To achieve state change or value transfer, executions must adhere to the rules of each level. Transactions that don’t satisfy the appropriate authorization will fail with response codes such as `INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE` when a sender is not authorized to carry out an operation. More operational-specific response codes will be returned where applicable e.g. `SPENDER_DOES_NOT_HAVE_ALLOWANCE`. *** ## Impact on Developers ### As a developer on Hedera, what should I do? Developers are strongly encouraged to test their applications with new contracts and UX using the new security model to avoid unintended consequences. * The new security model has been applied to contracts created from the mainnet [0.35.2 release](/networks/release-notes/services#0.35.2-hedera-smart-contract-service-security-model-changes) and onwards. * Existing contracts deployed before this upgrade will continue to use the previous security model for a limited time to allow for application/UX modifications. * The previous security model will only be maintained for approximately three months. The current target is for the network to remove the previous security model and for all contracts to follow the new model by the mainnet release of July 2023. * See a comprehensive list of the security updates made [here](#0.35.2). ### What does the change in the security model mean for smart contract developers? The security update involves changes to entity permissions during contract executions when modifying the state. In short, system contract calls (smart contract calls to the Hedera Token Service) are no longer executed with all upper caller privileges, even if the authorized user provides a signature. Understanding the process of contract executions for both externally owned accounts (EOAs) and contracts during regular and delegate calls is crucial. This process involves tracking how accounts, state (storage and value balance), and code may change as you progress through the chain of calls. #### Before (v1 model) In a regular call scenario, when a call is made to contract B, B’s code is executed in the context of its own state. This allows B to modify only its own state. The sender value also differs between the calls to highlight that the EOA made the first call and contract A made the second. #### After (v2 model) On the other hand, in a delegate call scenario, the call to contract B sees B’s code executed in the context of A’s state. This allows B to modify A’s state. The sender and recipient values are preserved from the first call as if the EOA initiated the call. In summary, a delegate call executes the calling contract's code in the context of the previous account, giving the code access to the previous account's state and blurring the lines of authorized state management. Applying this to the security model changes, the following table summarizes the authorization check changes.
ScenarioAuthorization checkOld ModelNew Model
Smart contract A can change its own state using a callsender = Contract AYY
Smart contract A can change EOA’s state via callsender = EOANN
Smart contract B can change contract A’s state via callsender = ANN
Smart contract A can change EOA’s state via delegate callsender = EOAYY
Smart contract B can change contract A’s state via delegate callsender = Contract AYY
System smart contracts can change another accounts (EOA or contract A or contract B) state via callsender = accountNN
System smart contract can change another accounts EOA or contract A or contract B) state via delegate callsender = accountNN
System contracts can change an accounts (EOA or contact A or contract B) state via call with the appropriate signaturesignature map contains signature of accounts (EOA or contact A or contract B respectively)YN
System smart contract can change another accounts (EOA or contact A or contract B) state via delegate call with the appropriate signaturesignature map contains signature of accounts (EOA or contact A or contract B)YN
Contract A or B can call a system contract via a call-YY
Contract A or B can call a system contract via a delegate call-YN
At the time of the change, the [HTS system contract](https://github.com/hiero-ledger/hiero-contracts/tree/main/contracts/token-service) was the only pathway to expose Hedera API functionality through Smart Contracts. As such, it’s fair to consider the differences between pre and post-security model updates when observing HTS system contract state-changing functions. #### Existing HTS system contract impacts summary
IHederaTokenService System Smart Contract Functionv1 Model Authorization Requirementsv2 Model Authorization RequirementsImpacts CodeSolution by Developers
approve, approveNFTsignature map contains accounts admin key signaturemsg.sender must be entity to be modifiedY

Upgrade contracts

or

Upgrade DApps to provide explicit user approval

\*Additional secure pathways: HIP 376 IERC.approve()

associateTokensignature map contains account admin key signaturemsg.sender must be entity to be modifiedY

Upgrade contracts

or

Upgrade DApps to provide explicit user associate

\*Additional secure pathways: HIP 719 IHRC.associate()

burnToken

signature map contains token burn key signature

or

Contract Id satisfies Token.supplyKey requirements

Contract Id satisfies Token.supplyKey requirementsYToken admin must set desired contract in Supply key
createFungibleToken, createFungibleTokenWithCustomFees, createNonFungibleToken, createNonFungibleTokenWithCustomFees

signature map contains affected account admin key signature(s) in treasury

or

autoRenew assignment case

msg.sender must be entity to be modified in treasury

or

autoRenew assignment case

Y-
cryptoTransfer

signature map contains sender admin key signature

or

Contract Id satisfies Entity.key requirements

msg.sender must be entity to be modified in treasury

or

autoRenew assignment case

YUpgrade DApps to provide explicit user approval.
deleteToken

signature map contains token admin key signature

or

Contract Id satisfies Token.adminKey requirements

Contract Id satisfies Token.adminKey requirementsYToken admin must set desired contract in admin key
dissociateToken, dissociateTokenssignature map contains admin key signaturemsg.sender must be entity to be modifiedY

Upgrade contracts

or

Upgrade DApps to provide explicit user dissociate

\*Additional secure pathways: HIP 719 IHRC.associate()

freezeToken

signature map contains freeze key signature

or

Contract Id satisfies Token.freezeKey requirements

Contract Id satisfies Token.freezeKey requirementsYToken admin must set desired contract in freeze key
grantTokenKyc

signature map contains kyc key signature

or

Contract Id satisfies Token.freezeKey requirements

Contract Id satisfies Token.kycKey requirementsYToken admin must set desired contract in kyc key
mintToken

signature map contains appropriate signature

or

Contract Id satisfies Token.supplyKey requirements

Contract Id satisfies Token.supplyKey requirementsYToken admin must set desired contract in Supply key
pauseToken

signature map contains pause key signature

or

Contract Id satisfies Token.pauseKey requirements

Contract Id satisfies Token.pauseKey requirementsYToken admin must set desired contract in pause key
revokeTokenKyc

signature map contains kyc key signature

or

Contract Id satisfies Token.freezeKey requirements

Contract Id satisfies Token.kycKey requirementsYToken admin must set desired contract in kyc key
setApprovalForAllsignature map contains admin key signaturemsg.sender must be entity to be modifiedY

Upgrade contracts

or

Upgrade DApps to provide explicit user associate

\*Additional secure pathways: HIP 376 IERC.setApprovalForAll()

transferFrom, transferFromNFT

signature map contains admin key signature

or

Spender must have been pre-approved an allowance

msg.sender must be entity to be modified in treasury

or

autoRenew assignment case

YUpgrade DApps to provide explicit user approval.
transferToken, transferTokens, transferNFT, transferNFTs

signature map contains admin key signature

or

Contract Id satisfies Entity.key requirements

or

Contract has been approved an allowance to spend by owner

msg.sender must be balance owner.

If not 1. Contract Id satisfies Entity.key requirements

or

2. Contract has been approved an allowance to spend by owner

YUpgrade DApps to provide explicit user approval.
updateTokenInfo, updateTokenExpiryInfo, updateTokenKeys

signature map contains token admin key signature

or

Contract Id satisfies Token.adminKey requirements

Contract Id satisfies Token.adminKey requirementsYToken admin must set desired contract in admin key
wipeTokenAccount, wipeTokenAccountNFT

signature map contains token wipe key signature

or

Contract Id satisfies Token.wipeKey requirements

Contract Id satisfies Token.wipeKey requirementsYToken admin must set desired contract in Wipe key
unfreezeToken

signature map contains token freeze key signature

or

Contract Id satisfies Token.freezeKey requirements

Contract Id satisfies Token.freezeKey requirementsYToken admin must set desired contract in freeze key
unpauseToken

signature map contains token pause key signature

or

Contract Id satisfies Token.pauseKey requirements

Contract Id satisfies Token.pauseKey requirementsYToken admin must set desired contract in pause key
**Note:** While the changes impact user experience, requiring more explicit steps, they more than proportionately increase user and network security across the board. The team continues to push diligently to provide the community with secure and scalable API solutions to enable them to build creative dApps and carve out their own shared world on the ledger. *** ## Security Upgrades * After the security incident on March 9th, the engineers conducted a thorough analysis of the Smart Contract Service and the Hedera Token Service system contracts. * As part of this exercise, we did not find any additional vulnerabilities that could result in an attack that that which we witnessed on March 9th. * The team also looked for any disparities between the expectations of a typical smart contract developer who is used to working with the Ethereum Virtual Machine (EVM) or ERC token APIs and the behaviors of the Hedera Token Service system contract APIs. Such differences in behavior could be used by a malicious smart contract developer in unexpected ways. * In order to eliminate the possibility of these behavioral differences being utilized as attack vectors in the future, the consensus node software will align the behaviors of the Hedera Smart Contract Service token system contracts with those of EVM and typical token APIs such as ERC 20 and ERC 721. * As a result, the following changes are made as of the mainnet 0.35.2 release on March 31st: * An EOA (externally owned account) will have to provide explicit approval/allowance to a contract if they want the contract to transfer value from their account balance. * The behavior of `transferFrom` system contract will be exactly the same as that of the ERC 20 and ERC 721 spec `transferFrom` function. * For HTS specific token functionality (e.g. Pause, Freeze, or Grant KYC), a contract will be authorized to perform the associated token management function only if the ContractId is listed as a key on the token (i.e. Pause Key, Freeze Key, KYC Key respectively). * The `transferToken` and `transferNFT` APIs will behave as `transfer` in ERC20/721 if the caller owns the value being transferred, otherwise it will rely on approve spender allowances from the token owner. * The above model will dictate entity (EOA and contracts) permissions during contract executions when modifying state. Contracts will no longer rely on Hedera transaction signature presence, but will instead be in accordance with EVM, ERC and ContractId key models noted. * As part of this release, the network will include logic to grandfather in previous contracts. * Any contracts created from this release onwards will utilize the stricter security model and as such will not have considerations for top-level signatures on transactions to provide permissions. * Existing contracts deployed prior to this upgrade will be automatically grandfathered in and continue to use the old model that was in place prior to this release for a limited time to allow for DApp/UX modification to work with the new security model. * The grandfather logic will be maintained for an approximate period of 3 months from this release. In a future release in July 2023, the network will remove the grandfather logic, and all contracts will follow the new security model. * Developers are encouraged to test their DApps with new contracts and UX using the new security model to avoid unintended consequences. If any DApp developers fail to modify their applications or upgrade their contracts (as applicable) to adhere to the new security model, they may experience issues in their applications. # Smart Contract Traceability Source: https://docs.hedera.com/evm/development/traceability After contracts have been deployed, you may want to further investigate the execution of a smart contract function call. Traces provide a comprehensive view of the sequence of operations and their effects, allowing for analysis, debugging, and auditing of smart contract behavior. The two types of useful traces: **➡** [**Call Trace**](#call-trace) **➡** [**State Trace**](#state-trace) *** ## Call Trace Contract **call trace** information captures the input, output, and gas details of all the nested smart contracts functions executed in a transaction. On Ethereum, these are occasionally called inner transactions but they simply capture snapshots of the message frame consideration the EVM encounters when processing a smart contract execution at each depth for all involved functions.
Input DataIt records the input data or parameters provided when calling a particular function within a smart contract. This input data is essentially the encoded form of the function signature and its arguments.
Output DataAfter executing the function, the trace information includes the output data returned by that function. This can be the result of the function's computation or any data it generates as part of its execution.
Gas DetailsLogs information about the gas consumed by each function call. Each operation within a function consumes a certain amount of gas, and this information is tracked to calculate the overall transaction cost.
This information can be queried using the transaction ID or Ethereum transaction hash. ℹ️ Detailed information for call trace can be found in the Hedera [protobuf](https://github.com/hashgraph/hedera-protobufs/blob/main/streams/contract_action.proto) and includes:
Call Trace Data Description
Call Operation Type

Specific type of operation performed during the execution of a smart contract or a transaction in the EVM. Example: “CALL” is an operation type use when a transaction invokes a function within a smart contract. It executes the function and can potentially modify the state of the contract.

``` OP_UNKNOWN = 0; OP_CALL = 1; OP_CALLCODE = 2; OP_DELEGATECALL = 3; OP_STATICCALL = 4; OP_CREATE = 5; OP_CREATE2 = 6; ```
Result Data The result data is the output or return values generated by the execution of a smart contract function or action. When a function call is executed, it may produce data as a result, such as computed values, status indicators, contract revert reason if any and the error if the transaction itself failed without an explicit REVERT
Result Data Type The "result data type" refers to the data type of the value returned by the function or method. For example, if you have a function add(a, b) that adds two numbers and returns the result, the result data type might be an integer if it returns the sum of the numbers.
Call Depth The level or depth of the current function call within the call stack. It provides information about the nested nature of function calls and helps track the sequence and hierarchy of function invocations during the execution of a smart contract.

The caller depth indicates how many functions have been called before the current function in the call stack. It starts at 0 for the initial function invocation and increments by 1 for each subsequent function call.

For example, the parent transaction would be represented as call depth 1 and first child would be at call depth 1.1 and child transaction 2 would be at call depth 1.2. Child transaction at depth 1.2 has two parents.
Caller The caller can be the ID of the account calling the contract or the ID of another smart contract calling the contract.

The first action in the tree can only come from an account. The rest of the actions in the call tree come from the contract.

When a smart contract function is invoked, either by an external account or by another contract, the caller address is recorded in the trace to identify the source of the function call. The caller address can be useful in understanding the context of the execution and determining the origin of the transaction or message that triggered the function call.
Recipient The address of the smart contract or account that receives a specific call or transaction. It represents the destination or target of the interaction within the EVM. The contract action can be directed to one of the following:

• Account: The account ID of the recipient if the recipient is an account. Only HBARs will be transferred.
• Contract: The contract ID if the recipient is a smart contract
• EVM address : If the contract action was directed to an invalid solidity address, what that address was
From The from Hedera contract calling the next contract.
To The contract receiving the call or being created.
Value/Amount The amount of hbars transferred within this call.
Gas Limit The gas is defined as the upper limit gas this contract call can spend.
Gas Used The amount of gas that was used for the contract call.
Input Bytes passed as an input data to this contract call
**Example**: *** ## State Trace Smart Contract state changes will now be tracked whenever a smart contract transaction modifies the state of the contract. This will enable developers to have a paper trail of the state changes that occurred for a contract from the time the contract was created. The state changes that will be tracked include each time a value is read or written to the smart contract. The storage slot represents the order in which the smart contract state is read or written. The value read reflects the storage value prior to the execution of the smart contract transaction. The value written, if present, represents the final updated value of the storage slot after the completion of the smart contract call. Transient states between the start and finish of the contract are not stored in the transaction record. ℹ️ Detailed information on state trace can be found in the [protobuf](https://github.com/hashgraph/hedera-protobufs/blob/main/streams/contract_state_change.proto) and includes:
State Trace DataDescription
Address

The smart contract EVM address.

Ex: 0000000000000000000000000000000000001f41

Contract ID

The smart contract ID.

Ex: 0.0.1234

SlotRefers to a storage location where data is stored within the contract's state. It can also be thought of as a variable or a storage unit that holds a specific value.
Value ReadThe current values of variables or data structures before making modifications. These values can be used to validate conditions, perform calculations, or trigger specific actions within the contract's code.
Value WrittenThe written or changed variables or data structures after the modification.
### Consensus Node Consensus nodes store sidecar records called `ContractStateChanges`. Each time a smart contract state changes, a new record will be produced that commemorates the state changes for the contract that took place. ### Mirror Node The Hedera [mirror node](/support/glossary#mirror-nodes) supports two rest APIs that return information about the smart contract’s state changes. This includes: * `/api/v1/contracts/{id}/results/{timestamp}` * `/api/v1/contracts/results/{transactionIdOrHash}` **Example:** ``` "state_changes": [ { "address": "0000000000000000000000000000000000001f41", "contract_id": "0.1.2", "slot": "0x00000000000000000000000000000000000000000000000000000000000000fa", "value_read": "0x97c1fc0a6ed5551bc831571325e9bdb365d06803100dc20648640ba24ce69750", "value_written": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" } ] ``` ### Hedera Mirror Node Explorer State trace can be viewed on a supported Hedera Network Explorer. # Troubleshooting Source: https://docs.hedera.com/evm/development/troubleshooting Diagnose and fix common issues when developing EVM smart contracts on Hedera. Most failures on Hedera fall into one of a few buckets: gas problems, reverts you can't decode, HBAR transfers that don't trigger your contract, decimal mismatches between SDK and EVM, or RPC issues that look like contract bugs but aren't. The sections below cover the patterns that account for most of them. ## Differences from Ethereum that bite Hedera is EVM-compatible, but a few things behave differently than Ethereum, and they account for most "this should work" tickets. ### Decimal handling: 8 vs 18 The native Hedera ledger uses 8 decimals for HBAR (1 ℏ = 10⁸ tinybars). The JSON-RPC relay scales values up to 18 decimals so they match Ethereum's `wei` convention. Inside an EVM contract, `msg.value`, `balance`, and `gasPrice` all use 18 decimals; the relay handles the conversion. The trap is when you mix native SDK calls and EVM contract calls in the same flow. You have to do the conversion yourself there, and the off-by-`10**10` bug is easy to write. ```solidity theme={null} // Inside a contract, msg.value is in 18-decimal wei (as on Ethereum). function deposit() external payable { require(msg.value >= 1 ether, "send at least 1 HBAR"); } ``` ### HBAR transfers don't always trigger `receive()` On Ethereum, sending ETH to a contract address triggers `receive()` or `fallback()`. On Hedera, a native HAPI `CryptoTransfer` (from an SDK or wallet operating at the Hedera level rather than the EVM level) credits the contract's underlying Hedera account directly. No EVM frame opens, so `receive()` doesn't run. EVM-native paths still behave normally: `call{value: ...}`, `transfer`, and internal CALL frames all invoke `receive()` / `fallback()` as expected. If you want contract logic to execute on the HAPI path, route the deposit through a `payable` call instead: ```solidity theme={null} // This runs the contract's payable function and fires events. (bool ok, ) = contractAddr.call{value: 1 ether}( abi.encodeWithSignature("deposit()") ); require(ok, "deposit failed"); ``` The full pattern is on the [Creating Smart Contracts](/evm/development/creating) page. ### ECDSA vs ED25519 keys Hedera supports both ECDSA (secp256k1) and ED25519. The EVM toolchain only handles ECDSA. Accounts created through MetaMask or via the JSON-RPC relay get ECDSA by default; accounts created through the native SDK can get either. ED25519 accounts can still hold HBAR and HTS tokens, but they can't sign EVM transactions. If you plan to interact through the EVM, pick ECDSA at account creation. ### Gas refund behavior Per [HIP-1249](https://hips.hedera.com/#hip-1249) (mirror node [v0.140.0 release notes](/networks/release-notes/mirror-node#v0-140-0)), unused gas is refunded in full, and only the gas you actually consumed is charged. The per-transaction limit remains 15M ([HIP-185](https://hips.hedera.com/#hip-185)). Hedera previously capped gas refunds at 20% of the limit, so setting a generous gas limit could quietly cost you. If you find guidance referencing the 20% cap, it's pre-HIP-1249 and no longer applies. See [Gas and Fees](/evm/development/gas-fees) for the full pricing model, intrinsic gas costs, and how to estimate fees. ### Historical queries have a retention window The relay supports `eth_call` and `eth_getStorageAt` at historical blocks, but only as far back as the mirror node behind it has data. Query a block older than that and the relay returns an error. For deep history, retry against a provider with longer retention (Arkhia, Validation Cloud, Hgraph, QuickNode, thirdweb). ## Where to ask for help `#developer-general` and `#smart-contracts`. Live answers from engineers and the community. JSON-RPC relay bugs and feature requests. Look up your transaction by hash to see the consensus-level result. Before filing an issue, look the transaction up on the mirror node. The SDK transaction ID format is `0.0.1234@1700000000.123456789`, but the REST API needs it in URL-safe form: `0.0.1234-1700000000-123456789`. So the full URL is `https://testnet.mirrornode.hedera.com/api/v1/transactions/0.0.1234-1700000000-123456789`. The mirror node tells you the consensus-level result, which is usually more specific than what the relay returns. # Verifying Smart Contracts Source: https://docs.hedera.com/evm/development/verifying Smart contract verification is the process of verifying that the smart contract bytecode uploaded to the network matches the expected smart contract source files. Verification is *not* required for contracts deployed on the Hedera network, but it is best practice and essential to maintaining the contract's security and integrity by identifying vulnerabilities that could be exploited, as smart contracts are immutable once deployed. It also enables transparency and builds trust within the user community by proving that the deployed bytecode matches the contract's original source code. Hedera Mainnet and Testnet are natively supported by [Sourcify](/support/glossary#sourcify), the open-source Solidity source code and metadata verification service hosted at [sourcify.dev](https://sourcify.dev). To verify a contract, submit your source files and metadata to Sourcify (directly via the web UI, the [v2 API](https://docs.sourcify.dev/docs/api/), or through your build tooling). Sourcify recompiles the submitted sources and compares them to the deployed bytecode. If a match is found, the contract's verification status is updated to either a [*Full (Perfect) Match*](https://docs.sourcify.dev/docs/full-vs-partial-match/#full-perfect-matches) or a [*Partial Match*](https://docs.sourcify.dev/docs/full-vs-partial-match/#partial-matches)*.* Once a contract is verified on Sourcify, [HashScan](https://hashscan.io/) and other community-hosted Hedera Mirror Node Explorers read its verification status directly from Sourcify and surface it to users. To learn what differentiates a *Full (Perfect) Match* from a *Partial Match*, check out the Sourcify documentation [here](https://docs.sourcify.dev/docs/full-vs-partial-match/). **Note**: Manual HashScan verification is temporarily disabled. Verify your contracts directly at [sourcify.dev](https://sourcify.dev) or through Foundry/Hardhat. Once verified there, the status will appear on HashScan automatically. For verification, you will need the following items: **➡** [**Smart Contract Source Code**](#smart-contract-source-code) **➡** [**The Metadata File**](#the-metadata-file) **➡** [**Deployed Smart Contract Address**](#deployed-smart-contract-address) *** ## Smart Contract Source Code This is the actual code for your smart contract written in Solidity. The source code includes all the contract's functions, variables, and logic. It's crucial for the verification process, where the deployed bytecode is compared to the compiled bytecode of this source code. #### Example: A simple `HelloWorld` Solidity smart contract: ```solidity theme={null} pragma solidity ^0.8.17; contract HelloWorld { // the contract's owner, set in the constructor address owner; // the message we're storing, set in the constructor string message; constructor(string memory message_) { // set the owner of the contract for 'kill()' owner = msg.sender; message = message_; } function set_message(string memory message_) public { // only allow the owner to update the message if (msg.sender != owner) return; message = message_; } // return a string function get_message() public view returns (string memory) { return message; } } ``` *** ## The Metadata File When you compile a Solidity smart contract, it generates a JSON metadata file. This file contains settings used when the smart contract was originally compiled. These settings can include the compiler version, optimization details, and more. The metadata file is crucial for ensuring that the bytecode generated during verification matches the deployed bytecode. > *Metadata is not part of the EVM spec because it's handled externally by compilers and tools like Sourcify. See Sourcify's Metadata documentation* [*here*](https://docs.sourcify.dev/docs/metadata/#metadata)*.* You have options for generating the metadata file. The recommended skill levels for each option are in parentheses. Choose the option that best fits your experience with smart contracts: To create a metadata file in Remix, compile your smart contract and the compiled artifacts will be saved in the `artifacts/` directory and the `.json` metadata file will be under `artifacts/build-info` and used for verification. Alternatively, you can copy and paste it from the Solidity compiler tab. Please see the image below. See the Remix IDE docs for more detailed documentation [here](https://remix-ide.readthedocs.io/en/latest/contract_metadata.html). **Note:** Taking the bytecode and metadata from Remix and then deploying that on Hedera results in a ***full (perfect) match***. Taking the bytecode and metadata from Remix *after* deploying the contract on Hedera results in a ***partial match*** or ***The deployed and recompiled bytecode don't match*** error. *The requirement for verification with a contract compiled in Remix is just the smart contract's Solidity file.* To create the `.json` metadata file with Hardhat, compile the contract using the `npx hardhat compile` command. The compiled artifacts will be saved in the `artifacts/` directory and the `.json` metadata file will be under `artifacts/build-info` and used for verification. See Sourcify Hardhat metadata documentation [here](https://docs.sourcify.dev/docs/metadata/#hardhat). **Note**: The requirement for verification with a contract compiled with Hardhat is only the `build-info` JSON file. To create the metadata file with Foundry, compile the contract using the `forge build` command. The compilation outputs to `out/CONTRACT_NAME` folder. The `.json` file contains the metadata of the contract under `"rawMetadata"` and `"metadata"` fields. However, you don't need to extract the metadata manually for verification. See Sourcify Foundry metadata documentation [here](https://docs.sourcify.dev/docs/metadata/#foundry). **Note**: The requirements for verification with a contract compiled with Foundry are both the `.json` metadata and the Solidity source file. You can pass the `--metadata` flag to the Solidity command line compiler to get the metadata output printed. ``` solc --metadata contracts/HelloWorld.sol ``` Write the metadata into a file with ``` solc --metadata contracts/HelloWorld.sol > metadata.json ``` **Note:`solc` vs. `solcjs`** **📣** `solcjs` will not generate the metadata using the `--metadata` flag. The option is only supported in `solc`. An example metadata file for the `HelloWorld` smart contract: ```json theme={null} { "compiler": "0.8.17", "language": "Solidity", "abi": [ { "inputs": [ { "internalType": "string", "name": "message_", "type": "string" } ], "stateMutability": "nonpayable", "type": "constructor" }, { "inputs": [], "name": "get_message", "outputs": [ { "internalType": "string", "name": "", "type": "string" } ], "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "string", "name": "message_", "type": "string" } ], "name": "set_message", "outputs": [], "stateMutability": "nonpayable", "type": "function" } ] } ``` *** ## Deployed Smart Contract Address Even though Hedera uses the `0.0.XXXXXXX` account ID format, it accommodates Ethereum's address format for EVM compatibility. Once your smart contract is deployed on Hedera's network, you'll receive an address like the one below. This serves as your deployed smart contract address. #### Example: An example deployed EVM smart contract address: ``` 0x403925982ef5a6461daba0a103bd6be20b9c4216 ``` ***Note**: The `0.0.XXXXXXX` smart contract address format can not be used in the verification process.* *** ## Verify Your Smart Contract Verify your contract directly at [sourcify.dev](https://sourcify.dev), via the [Sourcify v2 API](/reference/verification-api), or through Foundry / Hardhat tooling: *** ## Additional Resources **➡** [**Sourcify Docs**](https://docs.sourcify.dev/docs/intro) **➡** [**Smart Contract Verification API**](/reference/verification-api) **➡** [**HashScan Network Explorer**](https://hashscan.io/) **➡** [**Sourcify Verification UI**](https://sourcify.dev) **➡** [**Full vs Partial Match Docs**](https://docs.sourcify.dev/docs/full-vs-partial-match/) **➡** [**Hardhat Documentation**](https://hardhat.org/hardhat-runner/docs/guides/compile-contracts) **➡** [**Solidity Documentation**](https://docs.soliditylang.org/en/v0.8.23/) # Accounts, Signature Verification & Keys (ECDSA vs. ED25519) Source: https://docs.hedera.com/evm/differences/accounts-and-keys Compare Hedera and Ethereum account models, ECDSA vs ED25519 keys, alias handling, and ECRECOVER/isAuthorized signature verification on the EVM. ## Overview Migrating to Hedera’s EVM implementation involves understanding key differences in account models, signature verification, and key types. On Ethereum, addresses are derived from ECDSA public keys, and `ECRECOVER` is commonly used to validate signatures. Hedera, however, supports both ECDSA and ED25519 (Hedera-native account) keys, with dynamic key rotation and aliases that may not directly align with Ethereum’s static address model. This section helps you navigate ECDSA and ED25519 signature workflows, introduces the `isAuthorized` function from the system contract from [HIP-632](https://hips.hedera.com/hip/hip-632), and clarify how different account key scenarios map onto Hedera’s environment. ## Understanding Account Models and Aliases Hedera’s account model supports both ED25519 and ECDSA keys by identifying accounts by aliases instead of static addresses. This allows dynamic key rotation without changing an account’s ID, unlike EVM's static ECDSA-only approach. Signature validation varies accordingly: ED25519 keys use `isAuthorized` or `isAuthorizedRaw`, while Hedera's ECDSA accounts with aliases can still rely on `ECRECOVER`. ### **Clarifying Account ID vs. EVM Address** Hedera accounts have a native **Account ID** (e.g., `0.0.xxxx`) and can also have an **EVM Address from Public Key** (a 20-byte address like Ethereum's, derived from the ECDSA public key). The EVM Address from Public Key makes the account compatible with `ECRECOVER` and other familiar EVM tools. For more details, see the [Smart Contract Addresses](/evm/development/addresses) page. For a full explanation of how Hedera accounts work in EVM context — including hollow accounts (auto-created with no signing key) and accounts without an ECDSA key — see [Account Model for EVM Developers](/evm/development/accounts). ### **Working With ECDSA Accounts in Testing** If you are writing an Ethereum smart contract and need to interact with an ECDSA Hedera account identified by its **Account ID**, reference it by its **EVM Address** so that functions like `ECRECOVER` resolve the correct account, as long as the EVM Address is correctly set from the account's public key. Here are some considerations: * During testing, use the **EVM Address** returned by the account object, not the Account ID (e.g., `0.0.xxxx`). If the account was created with `setECDSAKeyWithAlias()`, that value is the **EVM Address from Public Key** (the 20-byte `Keccak-256(publicKey)` form) and works with EVM tools like Hardhat and Truffle and with `ECRECOVER`. If no alias was set at creation, the account falls back to the **EVM Address from Account ID** (the long-zero form), which is **not** compatible with `ECRECOVER`. Confirm which form your account uses before deploying. * Including this conversion step in your test setup saves time and confusion, ensuring your EVM-compatible smart contracts can reliably work with Hedera’s ECDSA accounts. ### **Key Permutations & Scenarios on Hedera** * **ECDSA Accounts:** * Behave similarly to standard EVM accounts. * Allow validation of ECDSA signatures with `ECRECOVER`. * Provide smooth interoperability with EVM tools and dApps. * **ED25519 Accounts:** * Require `isAuthorized` or `isAuthorizedRaw` for signature validation. * Support complex configurations like multi-key or threshold-based approval. * Enhance security and adaptability, but differ from EVM's static address. This flexibility enables interoperability and more robust security models than standard EVM environments. *** ## Using ECRECOVER for ECDSA Accounts on Hedera Hedera supports ECDSA accounts, allowing EVM developers to validate ECDSA signatures using familiar tools like `ECRECOVER`. ECDSA accounts on Hedera use aliases derived from `Keccak-256(publicKey)`, ensuring compatibility with Ethereum’s signature workflows. **Example: Verifying ECDSA Signatures Using ECRECOVER** ```solidity highlight={2} theme={null} function verifyECDSASignature(bytes32 messageHash, uint8 v, bytes32 r, bytes32 s) public pure returns (address) { return ecrecover(messageHash, v, r, s); } ``` **Key Considerations:** * ECDSA accounts on Hedera behave just like EVM accounts when validating signatures with `ECRECOVER`. * **Use ECDSA accounts when interacting with EVM-compatible dApps, wallets, or bridges for minimal friction.** *** ## Using System Contract Functions for ED25519 Accounts Hedera’s native key type is ED25519, which is not compatible with `ECRECOVER`. To accommodate ED25519 (Hedera-native) accounts and more complex configurations, HIP-632 introduces Hedera Account Service system contract functions: * [**isAuthorized**](/evm/hedera-services/system-contracts/account-service#isauthorized-address-message-signatureblob)**:** Validates multiple signatures, supporting threshold or multi-key accounts. * [**isAuthorizedRaw**](/evm/hedera-services/system-contracts/account-service#isauthorizedraw-address-messagehash-signatureblob)**:** Validates a single raw ED25519 signature, analogous to `ECRECOVER` but for ED25519 keys. **Example: Validating ED25519 Signatures** ```solidity highlight={4} theme={null} function verifyED25519Signature(address accountAlias, bytes32 messageHash, bytes memory signatureBlob) public returns (bool) { (bool success, ) = address(0x167).call( abi.encodeWithSignature( "isAuthorizedRaw(address,bytes32,bytes)", accountAlias, messageHash, signatureBlob ) ); return success; } ``` **Why This Matters for EVM Developers:** * **Hedera-Native Accounts:**\ Most Hedera accounts use ED25519 keys, so `isAuthorizedRaw` is essential for verifying their signatures. * **Multi-Key and Threshold Accounts:**\ Use `isAuthorized` for scenarios requiring multiple signatures, ensuring only properly authorized actions occur. ***Note**:* For detailed parameter formats, consult the [HIP-632](https://hips.hedera.com/hip/hip-632) specification and the Hedera Account Service [documentation](/evm/hedera-services/system-contracts/account-service). Ensure that `accountAlias`, `messageHash`, and `signatureBlob` adhere to the required formats outlined there. *** ## **Practical Use Case: Multi-Key Verification** Hedera supports advanced account configurations like multi-sig and threshold accounts, which may include both ECDSA and ED25519 keys. Using `isAuthorized`, you can enforce complex signing requirements, such as requiring multiple parties to sign before executing a contract operation. **Example: DAO Governance Using Multi-Sig** ```solidity highlight={3} theme={null} function validateDAOProposal(address accountAlias, bytes memory proposalData, bytes memory signatureBlob) public returns (bool) { (bool success, ) = address(0x167).call( abi.encodeWithSignature("isAuthorized(address,bytes,bytes)", accountAlias, proposalData, signatureBlob) ); return success; } ``` This example demonstrates how you might require multiple signatures to approve a DAO proposal, enhancing the security and trustworthiness of your governance mechanisms. *** ## Key Rotation: Adapting to Hedera’s Dynamic Model Standard EVM addresses are static since they are derived from a public key hash. Hedera, by contrast, supports dynamic key rotation, letting you update the keys controlling an account without changing the account’s address. **Why This Matters for EVM Developers:** * Your applications must dynamically validate the current set of keys each time rather than relying on a static key-to-address mapping. * By rotating keys, you can enhance security without migrating to a new address. **Example: Key Rotation in Smart Contracts** ```solidity theme={null} contract KeyRotationHandler { address public trustedSigner; constructor(address initialSigner) { trustedSigner = initialSigner; } function updateTrustedSigner(address newSigner) public { require(msg.sender == trustedSigner, "Not authorized"); trustedSigner = newSigner; } } ``` This simple pattern allows you to change the trusted signer as needed, reflecting real-world operational needs such as periodic key rotation to mitigate security risks. *** ### Additional References and Resources * [**Hedera SDKs**](/native/fundamentals) * [**Hedera Account Service**](/evm/hedera-services/system-contracts/account-service) * [**HIP-632 Specification**](https://hips.hedera.com/hip/hip-632) * [**Hedera Account Service System Contract**](https://github.com/hiero-ledger/hiero-contracts/tree/main/contracts/account-service) # Decimal Handling (8 vs. 18 Decimals) Source: https://docs.hedera.com/evm/differences/hbar-decimals ## **Overview** Managing token decimals is critical when working with HBAR, HTS tokens, and ERC tokens on Hedera, as each system has distinct precision standards. These differences impact how token balances are calculated, displayed, and transferred across various tools and environments. *** ## Token Decimal Comparison and API Context The table below compares the decimal handling of HBAR, HTS tokens, and ERC tokens on Hedera, incorporating details about their representation across APIs and services. This overview highlights differences in precision and context.
API/ServiceDecimalsExplanation
Hedera API (HAPI)8 decimalsHBAR is represented with 8 decimal places, aligning with its native smallest unit tinybar.
Hedera Smart Contract Service8 decimalsWithin the EVM environment, HBAR maintains 8 decimal places, consistent with its native representation.
JSON-RPC Relay (Arguments)8 decimalsWhen HBAR values are passed as arguments in JSON-RPC calls, they are represented with 8 decimal places.
JSON-RPC Relay (msg.value)18 decimalsFor compatibility with EVM tooling, msg.value in JSON-RPC Relay represents HBAR with 18 decimal places. Consequently, gasPrice also uses 18 decimal places in this context.
HTS TokensConfigurable (up to 8 decimals)HTS tokens allow token creators to define precision at token creation, offering flexibility for various use cases.
ERC TokensDefault 18 decimalsERC tokens on Hedera follow Ethereum token standards, with 18 decimals as the default unless specified otherwise.
**Key Impacts**: * Account for scaling differences when converting HBAR between APIs, especially when using JSON-RPC. * HBAR fees are always calculated in tinybars, regardless of the API or service used. * JSON-RPC’s use of 18 decimals ensures smooth integration with EVM tools and libraries. *** ## Conversion Helpers Utility functions are essential for managing discrepancies between HBAR (measured in tinybars, 8 decimals), HTS tokens (which can have configurable decimal places), and ERC tokens (measured in wei, 18 decimals). These conversions ensure consistency across your smart contracts, front-end applications, and APIs. **Code Example: Decimal Conversion Helpers** ```solidity wrap theme={null} // Convert from 18 decimals (weibar/wei) to 8 decimals (tinybar) function convertToTinybar(uint256 weiAmount) public pure returns (uint256) { // 1 tinybar = 10^10 weibar return weiAmount / (10 ** 10); } // Convert from 8 decimals (tinybar) to 18 decimals (weibar/wei) function convertToWei(uint256 tinybarAmount) public pure returns (uint256) { return tinybarAmount * (10 ** 10); } ``` Reference: [**Smart Contracts Gas and Fees**](/evm/development/gas-fees) *** ### **Additional Resources** * [**ERC-20 Token Standard**](/evm/tokens/erc20) * [**Hedera Token Service Documentation**](/learn/core-concepts/tokens) * [**HBAR Decimal Places Documentation**](/native/fundamentals/hbars#hbar-decimal-places) * [**Token Managed by Smart Contracts**](/evm/tokens) # Understanding Hedera's EVM Differences and Compatibility Source: https://docs.hedera.com/evm/differences/index Hedera's EVM-compatible environment lets you deploy Solidity smart contracts using Hardhat, Foundry, or Remix and connect with standard Ethereum tooling. Hedera's architecture introduces differences in account models, key management, token handling, and JSON-RPC behavior that affect how you build and migrate from Ethereum. This guide is for: * **EVM developers migrating to Hedera:** Understand key differences in Hedera's architecture, tokenomics, and tooling, including ED25519 key management and native system contracts (introduced in [HIP-632](https://hips.hedera.com/hip/hip-632)). * **Hedera-native developers adding smart contract functionality:** Learn how EVM contracts interact with Hedera's native services (HTS, HCS, HFS) and how to bridge both worlds. ## High-Level Differences: Hedera vs. Ethereum | **Feature** | **Hedera** | **Ethereum** | | ------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------- | | Consensus Mechanism | Asynchronous Byzantine Fault Tolerance (aBFT), Proof of Stake (PoS) | Byzantine Fault Tolerance (BFT), Proof of Stake (PoS) | | Transaction Fees | Low and predictable [fees](/networks/fees) | Variable gas fees; can spike during network congestion | | Governance Model | Governed by the Hedera Governing Council, comprising leading global organizations | Decentralized; governed by the Ethereum community | | Native Token | HBAR | ETH | | Token Standard | ERC-20 and ERC-721 supported; Hedera Token Service (HTS) enables native token issuance and management without smart contracts | ERC-20 and ERC-721 | | Network State | Virtual Merkle Tree | Merkle Patricia Trie | | Historical Data | Off-chain mirror nodes provide access to historical data and state queries | On-chain `stateRoot` | | Key Management | Supports [ED25519](/support/glossary#ed25519) (Hedera-native accounts), [ECDSA (secp256k1)](/support/glossary#ecdsa-secp256k1), and complex keys (keylist and threshold) | ECDSA (secp256k1) only | | Network Upgrades | Proposed through HIPs; governed by the Hedera Governing Council; backward compatible, not forks | Proposed and implemented through EIPs | *** ## Jumbo Ethereum Transactions Hedera supports jumbo Ethereum transactions (introduced in [HIP-1086](https://hips.hedera.com/hip/hip-1086)), allowing larger `callData` payloads to be included directly in the `ethereumData` field of `EthereumTransaction`. This aligns Hedera's EVM behavior more closely with Ethereum's, enabling seamless deployment of complex contracts. *📣 To learn more, including size limits, gas calculation, and limitations, see the* [*Ethereum Transaction SDK documentation*](/native/smart-contracts/ethereum-transaction)*.* *** ## EVM Developers: What Changes on Hedera The following topics cover the most common differences when coming from Ethereum: | **Topic** | **Description** | | ------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | | [Hedera Account Model & Aliases](/evm/differences/accounts-and-keys#understanding-account-models-and-aliases) | How Hedera's account structure differs from Ethereum's: ED25519 vs. ECDSA keys, dynamic key rotation, and aliases for EVM compatibility. | | [Decimal Handling](/evm/differences/hbar-decimals) | How to handle the difference between EVM's 18-decimal standard and Hedera's 8 decimals for accurate token calculations and conversions. | | [Key Rotation](/evm/differences/accounts-and-keys#key-rotation-adapting-to-hederas-dynamic-model) | Strategies for designing smart contracts that work with Hedera's dynamic key rotation model. | | [HBAR Transfers](/evm/differences/native-token-transfers) | Explicit handling of HBAR in Solidity contracts for native token flows. | | [JSON-RPC Relay](/evm/differences/json-rpc-differences) | How Hedera's JSON-RPC relay differs from standard EVM RPC APIs. | ## Hedera-Native Developers: Adding Smart Contracts If you're already building with Hedera's native services and want to add EVM smart contract functionality, see [Hedera-Native Developers Adding Smart Contracts](/evm/differences/native-devs). ## Additional Resources * [Getting Started for EVM Developers](/evm) * [JSON-RPC Documentation](/evm/development/json-rpc) * [Mirror Node API Documentation](/reference/rest-api) * [Java SDK](https://github.com/hiero-ledger/hiero-sdk-java), [Go SDK](https://github.com/hiero-ledger/hiero-sdk-go), [JavaScript SDK](https://github.com/hiero-ledger/hiero-sdk-js) # JSON-RPC Relay and EVM Tooling Source: https://docs.hedera.com/evm/differences/json-rpc-differences Learn how to use the JSON-RPC relay and familiar EVM tools to interact with the Hedera network. ## **Overview** Hiero’s JSON-RPC relay provides a familiar interface for EVM developers by supporting standard Ethereum JSON RPC methods. This compatibility means you can use popular EVM development tools (like Hardhat, Truffle, or Foundry) and wallets (like Metamask) to interact with Hedera’s network. However, Hedera’s unique state management model affects how you retrieve historical data and verify states, requiring a shift in approach from the standard EVM workflow. *** ## **Key Relay Features** The relay offers several advanced features that enhance dApp development on Hedera: #### **Real-Time Data and Event Filtering** The relay provides robust support for real-time data streaming and event filtering through its WebSocket server and Filter API methods. This allows applications to listen for on-chain events and receive updates as they happen. * WebSocket Support (`eth_subscribe`): Developers can establish a WebSocket connection to the relay (default: `ws://localhost:8546`) to subscribe to logs and newHeads events. This is ideal for applications that need to react instantly to new blocks or specific contract events. This functionality is enabled by HIP-694. * Filter API Methods: The relay supports the standard Ethereum Filter API, including `eth_newFilter`, `eth_getFilterChanges`, and `eth_getFilterLogs`. These methods allow you to create and query filters for historical logs and pending transactions, providing a powerful way to track contract activity. #### **Paymaster Support for Gasless Transactions** The JSON-RPC relay supports a paymaster feature, enabling gasless transactions for users. When this feature is enabled, the relay operator can sponsor transaction fees, allowing dApp users to interact with smart contracts without needing to hold HBAR for gas. This is ideal for improving user onboarding and creating seamless application experiences. **Key features of paymaster support include:** * **Gasless Transactions**: Users can send transactions with a gas price of 0. * **Operator-Sponsored Fees**: The relay operator covers the HAPI and Ethereum fees. * **Flexible Configuration**: Operators can enable paymaster support for all transactions (wildcard) or restrict it to a whitelist of specific smart contract addresses. **💡***For more details on how to configure and use the paymaster feature, please refer to the configuration details in the* [***Hiero JSON RPC Relay repository***](https://github.com/hiero-ledger/hiero-json-rpc-relay/blob/main/docs/configuration.md)**.** #### **Testing with Network Forking** Hedera now supports network forking, which allows you to test smart contracts against a live network's state without executing transactions on the actual network. This is a feature for development and debugging, as it lets you simulate transactions and contract interactions in a realistic environment. You can fork the Hedera network using both Hardhat and Foundry. For detailed instructions and examples, please refer to our tutorials: * [Forking the Hedera Network for Local Testing (Core Concepts)](/evm/development/forking) * [How to Fork the Hedera Network with Hardhat (Basic ERC-20)](/evm/tools/hardhat/forking-basic) * [How to Fork the Hedera Network with Hardhat (Advanced HTS)](/evm/tools/hardhat/forking-advanced) * [How to Fork the Hedera Network with Foundry (Basic ERC-20)](/evm/tools/foundry/forking) *** ## **Ethereum RPC API Behavior via JSON-RPC Relay** On Ethereum, methods like `eth_getBlockByNumber` return the true value of `stateRoot` that enables direct historical state verification. Hiero’s JSON-RPC relay, however, returns the root hash of an empty Merkle trie for the `stateRoot` value for compatibility. Instead of relying on it, you should query Hedera’s mirror nodes for historical states, event logs, and transaction details. #### **Example JSON-RPC Query Request** A request to `eth_getBlockByNumber` returns a `stateRoot`, but it’s not useful for historical verification on Hedera. Instead, use mirror node REST APIs to fetch the necessary historical information. ```shell theme={null} curl -X POST \ -H "Content-Type: application/json" \ -d "jsonrpc": "2.0", "method": "eth_getBlockByNumber", "params": [ "0x1", false ], "id": 1 } https://testnet.hashio.io/api ``` This returns the root hash of an empty Merkle trie for compatibility and not the actual `stateRoot` value. *** ## **Endpoints** The JSON RPC Relay methods implement a subset of the standard method: #### **Gossip Methods** These methods track the head of the chain. This is how transactions make their way around the network, find their way into blocks, and how clients find out about new blocks. | Method | Static Response Value | | --------------------------------------------------------------------------------------------------------- | --------------------- | | [`eth_blockNumber`](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_blocknumber) | N/A | | [`eth_sendRawTransaction`](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sendrawtransaction) | N/A | #### **State Methods** Methods that report the current state of all the data stored. The “state” is like one big shared piece of RAM, and includes account balances, contract data, and gas estimations. | Method | Static Response Value | | ---------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | | [eth\_getBalance](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getbalance) | n/a | | [eth\_getStorageAt](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getstorageat) | n/a | | [eth\_getTransactionCount](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gettransactioncount) | n/a | | [eth\_getCode](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getcode) | n/a | | [eth\_call](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_call) | n/a | | [eth\_estimateGas](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_estimategas) | generates and returns an estimate of the gas required for the transaction to complete | #### **History Methods** Fetches historical records of every block back to genesis. This is like one large append-only file, and includes all block headers, block bodies, uncle blocks, and transaction receipts. | Method | Static Response Value | | ------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------- | | [eth\_getBlockTransactionCountByHash](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getblocktransactioncountbyhash) | n/a | | [eth\_getBlockTransactionCountByNumber](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getblocktransactioncountbynumber) | n/a | | [eth\_getUncleCountByBlockHash](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getunclecountbyblockhash) | `null` | | [eth\_getUncleCountByBlockNumber](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getunclecountbyblocknumber) | `0x0` | | [eth\_getBlockByHash](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getblockbyhash) | `stateRoot` is always zero | | [eth\_getBlockByNumber](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getblockbynumber) | `stateRoot` is always zero | | [eth\_getTransactionByHash](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gettransactionbyhash) | n/a | | [eth\_getTransactionByBlockHashAndIndex](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gettransactionbyblockhashandindex) | n/a | | [eth\_getTransactionByBlockNumberAndIndex](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gettransactionbyblocknumberandindex) | n/a | | [eth\_getTransactionReceipt](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gettransactionreceipt) | n/a | | [eth\_getUncleByBlockHashAndIndex](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getunclebyblockhashandindex) | `null` | | [eth\_getUncleByBlockNumberAndIndex](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getunclebyblocknumberandindex) | `null` | **💡*****See the full list of methods*** [***here***](https://github.com/hiero-ledger/hiero-json-rpc-relay/blob/main/docs/rpc-api.md)***.*** ## **Supported EVM Development Tools**
Featureweb3jsTruffleethersHardhatRemix IDEFoundry
Transfer HBARS
Contract Deployment
Can use the contract instance after deploy without re-initialization
Contract View Function Call
Contract Function Call
Debug Operations\*\*
\*\***Debug operations** are supported via the `debug_traceTransaction` and `debug_traceBlockByNumber` methods. To enable these methods, you must set `DEBUG_API_ENABLED=true` in your relay configuration. For more information, see the [debugging documentation](https://github.com/hiero-ledger/hiero-json-rpc-relay/blob/main/docs/debugging-transactions.md). **Note**: Development tools usually make a lot of requests to certain endpoints, especially during contract deployment. Be aware of rate limiting when deploying multiple large contracts. **Note**: Enable `development mode` to correctly assert revert messages of contract calls with `hardhat-chai-matchers`. *** ## Additional Resources * [**Supported EVM Tooling**](https://github.com/hiero-ledger/hiero-json-rpc-relay/tree/main/tools) * [**JSON-RPC Relay Docs**](/evm/development/json-rpc) * [**Hiero JSON-RPC Relay Repo**](https://github.com/hiero-ledger/hiero-json-rpc-relay) # Integrating ED25519 Accounts and Advanced Features Into Smart Contracts Source: https://docs.hedera.com/evm/differences/native-devs/ed25519-integration ## Overview Hedera-native developers can leverage Hedera’s advanced account and key management features, including ED25519 accounts, multi-sig configurations, and threshold keys. To integrate seamlessly with EVM-compatible chains and applications, you’ll need to work with ECDSA key pairs. Hedera’s [HIP-632](https://hips.hedera.com/hip/hip-632) system contract functions—`isAuthorized` and `isAuthorizedRaw`—bridge this gap by enabling on-chain verification of both ED25519 and ECDSA signatures. This ensures you can extend Hedera-native security features into EVM-compatible smart contracts without compromising trust boundaries or functionality. *** ### **Bridging ED25519 Accounts with Solidity** Hedera’s ED25519 accounts are incompatible with Solidity’s `ECRECOVER` function, which supports ECDSA. To enable seamless integration, HIP-632 introduces two key system contract functions: * `isAuthorizedRaw`: Validates a single raw ED25519 signature. * `isAuthorized`: Validates multiple signatures or threshold key configurations, supporting multi-sig and advanced key schemes. These functions allow you to enforce the same account security models on-chain within smart contracts. **Basic Example: Validating a Single ED25519 Signature** Here’s a Solidity example for validating ED25519 signatures using the isAuthorizedRaw function. The function calls the system contract function (`isAuthorizedRaw`) to verify a raw signature on-chain. ```solidity theme={null} function verifyED25519Signature( address accountAlias, bytes32 messageHash, bytes memory signatureBlob ) public returns (bool) { (bool success, ) = address(0x167).call( abi.encodeWithSignature( "isAuthorizedRaw(address,bytes32,bytes)", accountAlias, messageHash, signatureBlob ) ); return success; } ``` **Use Case**: Validate ED25519 signatures on-chain to ensure that only authorized accounts execute sensitive operations. *** ### Integrating Multi-Sig and Threshold Keys On-Chain Hedera’s account model supports multi-sig and threshold key configurations. You can replicate these models on-chain with `isAuthorized` for robust access control. **Example: On-Chain Multi-Sig Verification** This example demonstrates requiring multiple valid signatures for critical contract actions: ```solidity theme={null} function validateMultiSig(address accountAlias, bytes memory proposalData, bytes memory signatureBlob) public returns (bool) { (bool success, ) = address(0x167).call( abi.encodeWithSignature("isAuthorized(address,bytes,bytes)", accountAlias, proposalData, signatureBlob) ); return success; } ``` **Use Case**: Ideal for governance scenarios like DAOs where multiple stakeholders must approve actions. **Advanced Example: Executing a DAO Proposal with Threshold Keys** In more complex scenarios, like DAOs, you can combine multi-sig verification with actionable contract logic to enforce threshold-based governance processes: ```solidity theme={null} function executeProposal(address daoAccount, bytes memory proposalData, bytes memory signatures) public { require(validateMultiSig(daoAccount, proposalData, signatures), "Invalid signatures"); // Execute the proposal logic here } ``` This ensures that even on-chain actions that modify state or issue tokens adhere to your established threshold-based governance processes. *** ### Supporting Dynamic Key Rotation Hedera’s dynamic key rotation allows you to update an account’s keys without changing its alias. By integrating `isAuthorized` checks into your contracts, your on-chain logic automatically remains in sync with the current authorized keys. Even as keys change over time to improve security or operational flexibility, your contracts don’t need to be redeployed or modified—`isAuthorized` will always reflect the latest configuration. *** ## **References** * [**HIP-632 Documentation**](https://hips.hedera.com/HIP/hip-632) * [**Hedera Account Service**](/evm/hedera-services/system-contracts/account-service) # Extending Token Management with Smart Contracts Source: https://docs.hedera.com/evm/differences/native-devs/extending-token-management ## **Overview** As a Hedera developer, you’re familiar with managing token supply through the Hedera Token Service (HTS). By integrating smart contracts, you can add programmable logic to your tokens, enabling conditional minting, burning, or transferring based on on-chain criteria. This approach allows you to design advanced tokenomics mechanisms tailored to your application’s needs. ### **Key Considerations for Tokenomics on Hedera** * Hedera does not support native HBAR burning; custom tokenomics strategies rely on HTS for minting and burning tokens. * The supply key grants critical permissions for token management, and its secure handling is essential. **Recommended Practices** * **Combine HTS and Smart Contracts**: * Use HTS system contract functions (`mintToken`, `burnToken`) to manage token supply programmatically within smart contracts. * Securely assign a supply key to your HTS token. * **Implement Access Control**: * Use multi-sig accounts or role-based permissions to secure supply modifications. * Validate input parameters in smart contract functions to prevent misuse. *** ### **Example: Minting and Burning HTS Tokens** The following smart contract demonstrates how to mint and burn HTS tokens using system contracts: ```solidity wrap theme={null} pragma solidity ^0.8.0; interface HederaTokenService { function mintToken(address token, int64 amount, bytes[] calldata metadata) external returns (int64 newTotalSupply); function burnToken(address token, int64 amount, bytes[] calldata metadata) external returns (int64 newTotalSupply); } contract TokenManager { HederaTokenService constant hts = HederaTokenService(0x167); address public tokenAddress; // HTS token with a supply key constructor(address _tokenAddress) { tokenAddress = _tokenAddress; } function mintTokens(int64 amount) external { hts.mintToken(tokenAddress, amount, new bytes[](0)); } function burnTokens(int64 amount) external { hts.burnToken(tokenAddress, amount, new bytes ); } } ``` *** ## Additional Resources * [**HTS System Contract Functions**](https://github.com/hiero-ledger/hiero-contracts/tree/main/contracts/token-service) * [**Tokens Managed by Smart Contracts**](/evm/tokens) * [**Accessing HTS Tokens Through the EVM**](/evm/hedera-services/hybrid) # For Hedera-Native Developers Adding Smart Contract Functionality Source: https://docs.hedera.com/evm/differences/native-devs/index ## **Introduction** As a Hedera-native developer, you are already familiar with Hedera’s features, such as ED25519-based key management, the Hedera Token Service (HTS), the Hedera Consensus Service (HCS), and workflows enabled by Hedera's SDKs. Integrating smart contracts into your existing workflows by leveraging Hedera’s EVM implementation allows you to embed on-chain logic directly into Hedera-native applications. This guide outlines the key considerations for adding EVM-compatible smart contract functionality without losing the performance and security benefits of Hedera’s architecture. *** ### **What You'll Learn**
TopicDescription
Cross-Chain CompatibilityManage ECDSA and ED25519 key types to enable interoperability with EVM-based ecosystems.
State ManagementAdapt to Hedera’s off-chain state model, leveraging mirror nodes and event logs for querying and validation.
Token ManagementExtend the Hedera Token Service with custom on-chain logic for minting, burning, and transferring tokens.
Signature VerificationImplement robust authorization mechanisms using isAuthorized and isAuthorizedRaw system contract functions.
### **Why Add Smart Contract Functionality?** Adding Hedera's EVM-compatible smart contract functionality allows developers to: * Build custom logic directly into your applications without relying solely on external SDKs. * Connect and interact with other EVM-compatible chains and tools. * Combine Solidity’s flexibility with Hedera’s predictable cost model, high throughput, and finality guarantees. *** ## Additional Resources * [**JSON-RPC Relay Guide**](/evm/development/json-rpc) * [**Mirror Node API Reference**](/reference/rest-api) * [**Hedera Token Service Documentation**](/learn/core-concepts/tokens) # JSON-RPC Relay and State Queries Source: https://docs.hedera.com/evm/differences/native-devs/json-rpc-state-queries ## Overview Hedera’s JSON-RPC relay provides compatibility with standard Ethereum JSON-RPC methods but is tailored to Hedera’s unique architecture and state management model. This page outlines key differences and practical guidance for developers adding smart contract functionality to Hedera-native applications. The content emphasizes adapting workflows for Hedera's consensus-driven model, understanding JSON-RPC’s behavior on Hedera, and leveraging tools like mirror nodes effectively. *** ## **Key Differences in JSON-RPC Behavior on Hedera** Hedera’s JSON-RPC relay acts as a compatibility layer, enabling EVM-based tooling to interact with Hedera. While it mirrors the standard Ethereum JSON-RPC API structure, its behavior reflects Hedera’s unique architecture:
FeatureHederaEthereum
State ManagementNo Merkle Patricia Trie. For RPC block data requests, it returns the root hash of an empty Merkle trie.Uses a Merkle Patricia Trie for stateRoot, enabling direct historical state verification.
Historical DataUse mirror nodes to retrieve historical events, balances, and transaction details.Historical data can be queried directly using Ethereum RPC methods like eth\_getBlockByNumber.
Testing FeaturesDoes not support contract snapshot features.Supports snapshots for fast and modular testing.
*** ## Contract Interactions * Use methods like `eth_call` and `eth_sendTransaction` to interact with deployed contracts via the JSON-RPC relay. * Fetch historical states or balances using mirror node REST APIs, as Hedera does not use a Merkle Patricia Trie. ### **Example** #### `eth_call` Request ```bash theme={null} curl -X POST \ -H "Content-Type: application/json" \ -d '{ "jsonrpc": "2.0", "method": "eth_call", "params": [ { "to": "0x1234567890abcdef1234567890abcdef12345678", "data": "0x6d4ce63c" }, "latest" ], "id": 1 }' \ https://testnet.hashio.io/api ``` #### Querying historical balances ```bash wrap theme={null} curl -X GET \ -H "Content-Type: application/json" \ "https://testnet.mirrornode.hedera.com/api/v1/accounts/0.0.123/balances?timestamp=1672549200" ``` *** ## Additional Resources * [**Mirror Node REST API Documentation**](/reference/rest-api) * [**JSON-RPC Methods on Hedera**](https://github.com/hashgraph/hedera-json-rpc-relay/blob/main/docs/rpc-api.md) # Handling HBAR Transfers in Contracts Source: https://docs.hedera.com/evm/differences/native-token-transfers ## Overview On Ethereum, sending ETH to a contract address automatically triggers the `receive()` or `fallback()` functions, allowing contracts to process incoming funds. On Hedera, these functions also exist but require HBAR to be explicitly sent via `contractCall` for them to execute. Direct HBAR transfers to a contract’s Hedera account won’t trigger any logic unless additional steps are taken. Fortunately, the core Solidity patterns—like using `transfer()`, `send()`, or `call()`—work the same way on Hedera, making it easy for developers familiar with EVM. This guide highlights these mechanisms, details the key Hedera-specific considerations, and provides examples to help you handle HBAR transfers in your smart contracts ### **Sending to Contract** In Solidity, there are three ways to transfer value to and from contracts: * `transfer()`: Sends a fixed amount of gas and reverts on failure. * `send()`: Sends a fixed amount of gas and returns `false` on failure instead of reverting. * `call()`: A low-level function for sending value that allows specifying gas and includes additional data payloads. These methods are supported on Hedera, ensuring compatibility with existing Solidity patterns. For more information on the supported functions, refer to the [Hiero Contracts Repo](https://github.com/hiero-ledger/hiero-contracts/tree/main). ### **Key Considerations** * **Fallback and Receive Functions**: When sending HBAR to a contract address via `contractCall`, Hedera behaves like Ethereum. If `receive()` or `fallback()` functions are defined in the contract, they will be triggered upon receipt of HBAR. * **Important Note**: Directly transferring HBAR to a contract’s Hedera account (not via `contractCall`) will not trigger these functions. To execute logic upon receipt, ensure transfers occur within the EVM environment. *** ## Example Contract Functions for HBAR Transfers Below is an example of contract functions and how HBAR transfers are handled using Solidity. These patterns are identical to those used for ETH on the EVM: ```solidity theme={null} // Handle incoming HBAR transfers receive() external payable { // Example logic for received HBAR emit HbarReceived(msg.sender, msg.value); } // Transfer HBAR using different methods function transferHbar(address payable _receiverAddress, uint _amount) public { _receiverAddress.transfer(_amount); } function sendHbar(address payable _receiverAddress, uint _amount) public { require(_receiverAddress.send(_amount), "Failed to send HBAR"); } function callHbar(address payable _receiverAddress, uint _amount) public { (bool sent, ) = _receiverAddress.call{value: _amount}(""); require(sent, "Failed to send HBAR"); } // Event for logging received HBAR event HbarReceived(address sender, uint256 amount); ``` **Suggested Tutorial** For developers newer to Solidity, we recommend exploring [Solidity courses](https://solidity-by-example.org/) to gain a deeper understanding of handling value transfers. A detailed tutorial on sending and receiving HBAR using Solidity smart contracts on Hedera can be found [here](/evm/tutorials/intermediate/send-receive-hbar). *** ### Additional Resources * [**Hiero Contracts**](https://github.com/hiero-ledger/hiero-contracts/tree/main) * [**Solidity Documentation**](https://docs.soliditylang.org/) * [**Solidity by Example**](https://solidity-by-example.org/) # Token Management with Hedera Token Service Source: https://docs.hedera.com/evm/differences/tooling-compatibility ## Overview Ethereum supports native ETH burning via mechanisms like [EIP-1559](https://ethereum.github.io/abm1559/notebooks/eip1559.html), but Hedera takes a different approach. The native HBAR token cannot be burned. Instead, developers can use the Hedera Token Service (HTS) to create and manage custom tokens with built-in minting and burning capabilities. ### Key Features for EVM Developers * **Supply Key** * Controls minting and burning of tokens. * Must be securely managed to prevent unauthorized actions. * **HTS System Contract** * System contract functions accessible via reserved address `0x167`. * Enable token creation, minting, and burning directly from Solidity contracts. * **Access Control** * Only addresses authorized by the supply key can mint or burn tokens. * Multi-signature (multi-sig) or threshold key configurations can enhance security. *** ### Minting and Burning Tokens with HTS * **Minting Tokens**: Introduce new tokens for incentives, rewards, or liquidity. * **Burning Tokens**: Remove tokens to increase scarcity or meet regulatory requirements. #### Code Example: HTS Mint/Burn ```solidity wrap theme={null} // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; interface HederaTokenService { function createFungibleToken( address treasury, uint64 initialSupply, string memory tokenName, string memory tokenSymbol, uint32 decimals ) external returns (address tokenAddress); function mintToken(address token, int64 amount, bytes[] calldata metadata) external returns (int64 newTotalSupply); function burnToken(address token, int64 amount, bytes[] calldata metadata) external returns (int64 newTotalSupply); } contract TokenManager { HederaTokenService constant hts = HederaTokenService(0x167); address public token; constructor(address treasury) { // Create a fungible token with an initial supply of 1,000 units // Token parameters: name = "MyHederaToken", symbol = "MHT", decimals = 8 token = hts.createFungibleToken(treasury, 1000, "MyHederaToken", "MHT", 8); } // Mint additional tokens. Ensure that msg.sender holds the supply key or is authorized. function mintMoreTokens(int64 amount) external { // Metadata array left empty, but can be used for NFT-like functionality or extra data hts.mintToken(token, amount, new bytes[](0)); } // Burn existing tokens. Ensure the caller is authorized via supply key management. function burnSomeTokens(int64 amount) external { hts.burnToken(token, amount, new bytes[](0)); } } ``` **Important Notes** * Ensure the caller holds the supply key. * Associate the treasury account with the token for successful operations. * Minting and burning fail without proper key authorization. *** ## Additional Resources * [**Access HTS Tokens Through the EVM**](/evm/hedera-services/hybrid/erc-compatibility) * [**HTS System Contract Functions**](https://github.com/hiero-ledger/hiero-contracts/tree/main/contracts/token-service) # Create Tokens Source: https://docs.hedera.com/evm/hedera-services/hts-solidity/create-tokens Create fungible and non-fungible HTS tokens directly from Solidity via the 0x167 system contract. The HTS system contract at `0x167` lets a Solidity contract create native HTS tokens. The resulting token is a real HTS token: same association rules, same mirror node REST responses, same HashScan view as an SDK-created one. You can operate on it through the HTS interface or through ERC-20 / ERC-721 redirects. ## At a glance | Field | Value | | ---------------- | -------------------------------------------------------------------------------------------------------------------------------- | | Contract address | `0x167` | | Reference HIPs | [HIP-358 (token creation)](https://hips.hedera.com/hip/hip-358), [HIP-206 (HTS precompile)](https://hips.hedera.com/hip/hip-206) | | Solidity source | [hiero-contracts/contracts/token-service](https://github.com/hiero-ledger/hiero-contracts/tree/main/contracts/token-service) | | Key functions | `createFungibleToken`, `createNonFungibleToken`, `createFungibleTokenWithCustomFees`, `createNonFungibleTokenWithCustomFees` | ## Why use this instead of a plain ERC-20? Two practical reasons. The first is compliance features. HTS tokens get native support for KYC keys, freeze, pause, wipe, supply caps, and royalty fees, and the network enforces them. If you build the same controls into an ERC-20 contract, you write them yourself and pay gas every time they fire. The second is pricing. HTS operations are priced in USD and paid in HBAR by the network. ERC-20 operations are priced in EVM gas, which scales with whatever you put in your contract. If you don't need any of that, a plain ERC-20 is simpler and works fine. The choice is per-token; nothing stops you from using both in one app. ## Required imports The helper library is `HederaTokenService.sol`, in the [hiero-contracts repository](https://github.com/hiero-ledger/hiero-contracts). Copy these files into your `contracts/` directory: ```text theme={null} contracts/ ├── HederaTokenService.sol # Wrapper that handles call/response codes ├── IHederaTokenService.sol # Raw interface (function signatures, structs) ├── HederaResponseCodes.sol # Numeric response codes (SUCCESS, INVALID_TOKEN_ID, ...) — from contracts/common/ ├── ExpiryHelper.sol # Builds the Expiry struct ├── FeeHelper.sol # Builds FixedFee, FractionalFee, RoyaltyFee structs └── KeyHelper.sol # Builds HederaToken.TokenKey entries ``` ## Example: fungible token ```solidity theme={null} // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.22; import "./HederaTokenService.sol"; import "./IHederaTokenService.sol"; import "./HederaResponseCodes.sol"; import "./KeyHelper.sol"; import "./ExpiryHelper.sol"; contract TokenFactory is HederaTokenService, KeyHelper, ExpiryHelper { event TokenCreated(address tokenAddress); function createFungible( string memory name, string memory symbol, int64 initialSupply, int32 decimals ) external payable returns (address tokenAddress) { // Build the supply key. This contract will be authorized to mint more. IHederaTokenService.TokenKey[] memory keys = new IHederaTokenService.TokenKey[](1); keys[0] = getSingleKey( KeyType.SUPPLY, KeyValueType.CONTRACT_ID, address(this) ); IHederaTokenService.HederaToken memory token; token.name = name; token.symbol = symbol; token.treasury = address(this); token.memo = "created via system contract"; token.tokenSupplyType = false; // false = infinite supply token.maxSupply = 0; token.freezeDefault = false; token.tokenKeys = keys; token.expiry = createAutoRenewExpiry(address(this), defaultAutoRenewPeriod); // Token creation costs HBAR (rent); forward msg.value to the precompile. (int responseCode, address created) = HederaTokenService.createFungibleToken( token, initialSupply, decimals ); require(responseCode == HederaResponseCodes.SUCCESS, "HTS token create failed"); emit TokenCreated(created); return created; } } ``` ## Example: non-fungible token ```solidity theme={null} function createNft( string memory name, string memory symbol ) external payable returns (address tokenAddress) { IHederaTokenService.TokenKey[] memory keys = new IHederaTokenService.TokenKey[](1); keys[0] = getSingleKey(KeyType.SUPPLY, KeyValueType.CONTRACT_ID, address(this)); IHederaTokenService.HederaToken memory token; token.name = name; token.symbol = symbol; token.treasury = address(this); token.tokenSupplyType = true; // true = finite supply token.maxSupply = 10_000; token.tokenKeys = keys; token.expiry = createAutoRenewExpiry(address(this), defaultAutoRenewPeriod); (int responseCode, address created) = HederaTokenService.createNonFungibleToken(token); require(responseCode == HederaResponseCodes.SUCCESS, "HTS NFT create failed"); return created; } ``` ## Paying for it Token creation costs HBAR. The caller has to forward enough `msg.value` to cover the `TokenCreate` transaction fee, which buys the token its initial auto-renew period (\~92 days). The current base fee is around \$1 USD worth of HBAR for both fungible and non-fungible tokens. Two important things to know about how Hedera handles the money: * **Gas is charged on consumption.** Per HIP-1249, Hedera refunds 100% of unused gas, and the per-transaction limit is 15M (HIP-185). Set a generous gas limit; you only pay for what you actually use. * **Excess `msg.value` is not refunded.** Anything you forward beyond what the precompile consumes for the `TokenCreate` fee stays in the calling contract's balance. There is no automatic refund to the EOA. The practical pattern: compute the exact tinybars via the [Exchange Rate system contract](/evm/hedera-services/system-contracts/exchange-rate) just before the call, or build a refund step into your contract that returns leftover HBAR to `msg.sender` after the precompile call. ```solidity theme={null} // Compute the exact value just before the call, then forward only that amount. // 1.5 USD in tinycents = 1.5 * 10^8 tinycents. Gives a small safety margin // over the ~$1 base fee. uint256 tinybars = IExchangeRate(0x168).tinycentsToTinybars(15 * 10**7); uint256 wei_ = tinybars * 10**10; // tinybars (8 decimals) -> wei (18 decimals) TokenFactory(factory).createFungible{value: wei_}("MyToken", "MTK", 1_000_000, 2); ``` Token creation fails with `INSUFFICIENT_PAYER_BALANCE` if `msg.value` doesn't cover the fee. If you can't compute the exact amount, pass extra and refund the leftover from inside your contract. Don't expect Hedera to do it for you. ## Token keys The `HederaToken.tokenKeys` array decides who can do what to the token. Each entry is a `(keyType, keyValue)` pair: | Key | Authorizes | | -------------- | ------------------------------------------------- | | `ADMIN` | Updating token properties and rotating other keys | | `SUPPLY` | Minting and burning | | `FREEZE` | Freezing and unfreezing accounts | | `WIPE` | Wiping tokens from accounts | | `KYC` | Granting and revoking KYC status | | `PAUSE` | Pausing all token operations | | `FEE_SCHEDULE` | Updating the custom-fee schedule | | `METADATA` | Updating NFT serial-number metadata (HIP-657) | Build each entry with `KeyHelper.getSingleKey(KeyType.X, KeyValueType.Y, address)`. Common `KeyValueType` values: `CONTRACT_ID` (the contract signs implicitly), `INHERIT_ACCOUNT_KEY` (use the caller's key), `ED25519` / `ECDSA` (provide a raw public key). ## See also Full function reference for the HTS precompile, including transfer, mint, burn, freeze, pause, and KYC operations. # ERC/EVM-Compatible Tokenization Source: https://docs.hedera.com/evm/hedera-services/hybrid/erc-compatibility Hedera provides full compatibility with ERC token standards through its EVM smart contract support, allowing developers to deploy and interact with ERC-20, ERC-721, and other EVM-based tokens. By integrating ERC standards with Hedera’s scalability, security, and low fees, developers can use familiar EVM tooling while benefiting from Hedera’s performance optimizations. *** ## **Why Choose ERC/EVM Tokenization on Hedera?** * Deploy ERC-20, ERC-721, and other EVM-based contracts directly on Hedera's EVM implementation. * Use EVM-native tools like Hardhat, Web3.js, ethers.js, and Remix to interact with smart contracts. * Interact with smart contracts via JSON-RPC relay, maintaining a familiar EVM development workflow. * Achieve greater scalability and efficiency, with predictable low-cost transactions and higher throughput than Ethereum. This makes Hedera an ideal platform for EVM developers looking for high-performance alternatives without modifying their existing smart contracts. *** ## **ERC Token Standards on Hedera** Hedera supports multiple ERC token standards, allowing developers to deploy smart contracts that interact seamlessly with EVM dApps and wallets.
Token StandardDescriptionUse Cases
ERC-20Fungible token standardCryptocurrencies, governance tokens
ERC-721Non-fungible token (NFT) standardDigital art, collectibles, gaming assets
ERC-3643Regulated real-world asset (RWA) token standardSecurities, compliant digital assets
ERC-1363Payable tokens supporting direct contract paymentsSubscription models, in-app purchases
These standards enable the deployment of any smart contract, including DeFi applications and tokenization contracts like ERC-20 and ERC-721 tokens. This compatibility alows EVM developers to leverage familiar workflows, tools and, frameworks on Hedera. *** ## Deploying and Interacting with ERC Tokens on Hedera ### **Using JSON-RPC for EVM Tooling** Hedera provides a JSON-RPC relay, making it easy for developers to interact with smart contracts using EVM-native tools. These tools provide standard EVM developer workflows on Hedera's EVM environment. Developers can use the same JSON-RPC methods as Ethereum, ensuring compatibility with dApps, wallets, and DeFi protocols.
ToolsDescription
HardhatDeploy and test smart contracts.
Web3.js / ethers.js Query and interact with contracts.
Remix IDEDeploy smart contracts using a browser-based IDE.
### **HTS Tokens as ERC-20/ERC-721 via Facade Contracts** Hedera provides facade contracts (per HIP-218 and HIP-376) that allow HTS-native tokens to function as ERC-20 or ERC-721 tokens. With these contracts, developers can leverage Hedera’s efficiency while maintaining EVM compatibility. ​A facade contract on Hedera acts as a built-in adapter, allowing Hedera Token Service (HTS) tokens to function seamlessly as standard ERC-20 or ERC-721 tokens within EVM-compatible (EVM) environments. This integration enables developers to interact with HTS tokens using familiar Ethereum interfaces, such as `transfer()`, `approve()`, and `transferFrom()`, without requiring modifications to existing Ethereum wallets or decentralized applications (dApps). Under the hood, when an EVM-compatible tool interacts with an HTS token's facade contract, the call is delegated to Hedera's native token service. This design ensures that HTS tokens can be managed and transacted using standard Ethereum tooling, providing a seamless developer experience. ​ In summary, facade contracts provide a bridge between Hedera's native token services and the Ethereum ecosystem, enabling developers to leverage Hedera's performance benefits while maintaining compatibility with established Ethereum standards and tools.​
Facade ContractsDescription
IHRC904AccountFacade.sol[https://github.com/hiero-ledger/hiero-contracts/blob/main/contracts/account-service/IHRC904AccountFacade.sol](https://github.com/hiero-ledger/hiero-contracts/blob/main/contracts/account-service/IHRC904AccountFacade.sol)
IHRC906AccountFacade.sol[https://github.com/hiero-ledger/hiero-contracts/blob/main/contracts/account-service/IHRC906AccountFacade.sol](https://github.com/hiero-ledger/hiero-contracts/blob/main/contracts/account-service/IHRC906AccountFacade.sol)
IHRC755ScheduleFacade.sol[https://github.com/hiero-ledger/hiero-contracts/blob/main/contracts/schedule-service/IHRC755ScheduleFacade.sol](https://github.com/hiero-ledger/hiero-contracts/blob/main/contracts/schedule-service/IHRC755ScheduleFacade.sol)
IHRC904TokenFacade.sol[https://github.com/hiero-ledger/hiero-contracts/blob/main/contracts/token-service/IHRC904TokenFacade.sol](https://github.com/hiero-ledger/hiero-contracts/blob/main/contracts/token-service/IHRC904TokenFacade.sol)
### Token Associations When transferring HTS tokens on Hedera, recipients must associate the token with their account before receiving it. [Learn more about token auto associations and fees](/learn/core-concepts/tokens/airdrops#auto-associations-and-fees). ### **Synthetic Events for Tokens Managed by Smart Contracts** Smart contract tokens like ERC-20 and ERC-721 emit events, creating contract logs that developers can query or subscribe to. Hedera Token Service (HTS) tokens do not natively generate such event logs. As a solution to this limitation, Hedera Mirror Nodes generate synthetic event logs, enabling event-driven workflows to mimic the behavior of smart contract tokens for HTS transactions. Synthetic events are generated for transactions such as: * `CryptoTransfer` * `CryptoApproveAllowance` * `CryptoDeleteAllowance` * `TokenMint` * `TokenWipe` * `TokenBurn` This feature enables developers to effectively monitor HTS token activities as if they were smart contract tokens. An example code implementation demonstrating using ethers.js to listen to synthetic events can be found [here](https://github.com/ed-marquez/hedera-example-hts-synthetic-events-sdk-ethers). ## Video Resource