<!-- tempo-docs-context -->
> Source: [/docs/quickstart/evm-compatibility](https://tempo.xyz/developers/docs/quickstart/evm-compatibility.md)
> Section: [Tempo EVM](https://tempo.xyz/developers/docs/development.md). Build on Tempo EVM: wallets and keys, payments, transactions and fees, TIP-20 Tokens, contracts, exchange, network details, nodes, protocol specifications, and changelog.
> [Documentation index](https://tempo.xyz/developers/llms.txt) · [Docs skill](https://tempo.xyz/developers/SKILL.md)

> Tempo MCP: Use `search`, `find_pages`, `read_page`, and `code` at `https://mcp.tempo.xyz` for Tempo and related documentation.
> If an indexed page is missing or reflects an older site, read this site’s [documentation index](https://tempo.xyz/developers/llms.txt) and Markdown pages directly.

<span id="tempo-evm-differences" />

# EVM differences

Tempo supports EVM smart contracts and familiar Ethereum tools. Review these differences when porting an application, wallet, or contract, especially native-balance checks, fee-token selection, and gas estimates.

The execution environment targets the **Osaka** EVM hard fork. Start with [Network details](https://tempo.xyz/developers/docs/quickstart/connection-details) for chain configuration or [Smart contracts](https://tempo.xyz/developers/docs/network/contracts) for deployment.

## Wallet differences

By default, all existing functionality will work for EVM-compatible wallets, with only a few quirks. For developers of wallets, we strongly encourage you to implement support for Tempo Transactions over regular EVM transactions. See the [transaction differences](https://tempo.xyz/developers/docs/quickstart/evm-compatibility#transaction-differences) for more.

:::tip
If you are building a wallet, read our [guide for wallet developers](https://tempo.xyz/developers/docs/quickstart/wallet-developers).
:::

### Handling ETH (native token) Balance Checks

Remember that on Tempo, there is no native gas token.

Many wallets and applications check a user's "native account balance" before letting them complete some action. In this scenario, you might see an error message like "Insufficient balance".

This stems from the return value of the `eth_getBalance` RPC method. When a wallet calls this method, it expects a hex string representing the "native token balance", hard-coded to be represented as an 18-decimal place number.

On Tempo, the `eth_getBalance` method returns a hex string representing an extremely large number. Specifically it returns: `0x9612084f0316e0ebd5182f398e5195a51b5ca47667d4c9b26c9b26c9b26c9b2` which is represented in decimals as 4.242424242424242e+75.

Our recommendation to wallets and to applications using this method is to remove this balance check, and to not represent any "native balance" in your user's UI. This will allow users to complete actions without being blocked by balance checks.

We endorse [this proposed ERC](https://github.com/ethereum/ERCs/pull/1220) to standardize this behavior.

### Specifying a Native Token Currency Symbol

Sometimes wallets will need to specify the currency symbol for the native token. On Tempo, there is no native token, but fees are denominated in USD. So, we recommend using the currency symbol "USD".

## Transaction differences

### Dealing with the fee token selection

Tempo does not have a native gas token. Instead, fees are denominated in USD and fees can be paid in supported USD-denominated TIP-20 tokens. For Tempo Transactions, the `fee_token` field selects the token. When conversion is needed, the Fee AMM must have enough liquidity for the validator's preferred token. See [Fees](https://tempo.xyz/developers/docs/network/fees) for configuration and estimates.

If your transactions are not using Tempo Transactions, there is a cascading fee token selection algorithm that determines the default fee token based on the user's preferences and the contract being called.

This preference system is specified [here](https://tempo.xyz/developers/docs/protocol/fees/spec-fee#fee-token-preferences) in detail.

#### Consideration 1: Setting a user default fee token

As specified in the preference system above, the simplest way to specify the fee token for a user is to set the user default fee token. Read about how to do that [here](https://tempo.xyz/developers/docs/protocol/fees/spec-fee#account-level) on behalf of an account.

#### Consideration 2: Paying fees in the TIP-20 contract being interacted with

If no account preference is set, a top-level `transfer` or `transferWithMemo` call to a USD-denominated TIP-20 token uses that token for fees. Other TIP-20 methods do not automatically select their target token. For example, if the user is calling the `transfer` method on a TIP-20 token with a symbol of "USDG", the default fee token would be "USDG".

Importantly, note that the `amount` field in this case is sent in full. So, if the user is calling the `transfer` method on a TIP-20 token with a symbol of "USDG" with the `amount` field set to `1000 * 10^6` base units, the full 1,000 USDG is transferred and fees are deducted separately. A receiver's receive policy can redirect that delivery to the ReceivePolicyGuard.

#### Consideration 3: The fallback in the case of a non-TIP-20 contract

If neither an account preference nor contract-specific inference applies, the EVM transaction defaults to pathUSD. Eligible Stablecoin DEX swap calls instead infer their input token. Thus, in order to send transactions to non-TIP-20 contracts, the wallet must hold some balance of pathUSD, or set an account fee token such as [OUSD](https://tempo.xyz/developers/docs/guide/ousd) with `setUserToken` on the FeeManager so it can pay fees in OUSD instead.

On the Tempo Testnet, pathUSD is available from the [faucet](https://tempo.xyz/developers/docs/quickstart/faucet).

If a wallet wants to submit a non-TIP20 transaction without having to submit the above transaction, we recommend investing in using [Tempo Transactions](https://tempo.xyz/developers/docs/guide/tempo-transaction) instead.

<span id="vm-layer-differences" />

## VM differences

At the VM layer, all opcodes are supported out of the box. Due to the lack of a native token, native token balance is always returning zero balances.

### State Creation Costs

Tempo's [state creation costs](https://github.com/tempoxyz/tempo/blob/main/tips/tip-1000.md) are higher to prevent state growth attacks:

| Operation | Tempo | Ethereum |
|-----------|-------|----------|
| New storage slot (SSTORE 0→non-zero) | 250,000 gas | 20,000 gas |
| Account creation | 250,000 gas | 0 gas |
| Contract creation per byte | 1,000 gas | 200 gas |
| Transaction gas cap | 30M gas | 16,777,216 gas (EIP-7825) |

This means transfers to new addresses cost ~300k gas, and contract deployments cost 5-10x more than on Ethereum. Update your `gas_limit` estimates accordingly.

### Balance Opcodes and RPC Methods

| Feature | Behavior on Tempo | Alternatives |
|---------|-------------------|--------------|
| **`BALANCE` and `SELFBALANCE`** | Will always return 0 | Use TIP-20 `balanceOf` instead |
| **`CALLVALUE`** | Will always return 0 | There is no alternative |

:::info
We are exploring transaction level introspection for Tempo Transactions, with an ability to declare things like `tx.fee_token` and `tx.fee_payer` in Solidity.
:::

<span id="consensus--finality" />

## Consensus and finality

Tempo uses **Simplex BFT consensus** with a permissioned validator set at launch, providing deterministic finality, unlike Ethereum's finality gadget which takes approximately 12 minutes.

Block times are targeted at ~0.5 seconds compared to Ethereum's ~12 second slots.
