# Ethereum & Merlin Differences

A number of technical details differ between Ethereum mainnet's EVM and Merlin's zkEVM.&#x20;

For the average Solidity developer, these details won't affect your development experience.

### EVM Opcodes

| Opcode                      | Status    | Merlin Behavior                                                                                                                                                                    |
| --------------------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `SELFDESTRUCT`              | Supported | Replaced by SENDALL. It sends remaining value to address, without any other status change.                                                                                         |
| `EXTCODEHASH`               | Supported | It returns the hash of the contract bytecode from the zkEVM state tree without checking if the account is empty.                                                                   |
| `DIFFICULTY` / `PREVRANDAO` | Supported | It returns "0" instead of a random number as in the EVM.                                                                                                                           |
| `NUMBER`                    | Supported | It returns the number of processable transactions, which is actually the number of transactions processed on the rollup, instead of current block's number.                        |
| `BLOCKHASH`                 | Supported | It is the state root at the end of a processable transaction and is stored on the system smart contract. It returns all previous block hashes instead of just the last 256 blocks. |
| `JUMPDEST`                  | Supported | It is allowed in PUSH bytes to avoid runtime bytecode analysis.                                                                                                                    |
| `BASEFEE`                   | Invalid   | Disabled. If the opcode is encountered, the transaction will be reverted.                                                                                                          |
| `BLOBHASH`                  | Invalid   | Disabled. If the opcode is encountered, the transaction will be reverted.                                                                                                          |
| `BLOBBASEFEE`               | Invalid   | Disabled. If the opcode is encountered, the transaction will be reverted.                                                                                                          |
| `TLOAD`                     | Invalid   | Disabled. If the opcode is encountered, the transaction will be reverted.                                                                                                          |
| `TSTORE`                    | Invalid   | Disabled. If the opcode is encountered, the transaction will be reverted.                                                                                                          |
| `MCOPY`                     | Invalid   | Disabled. If the opcode is encountered, the transaction will be reverted.                                                                                                          |

`MCOPY`, `TSTORE`, `TLOAD`, `BLOBHASH` and `BLOBBASEFEE` are Opcodes from the Cancun upgrade. We recommend using `shanghai` as your EVM target and avoiding using a Solidity version higher than `0.8.23`. Otherwise make sure you're not using those invalid opcodes.

`BASEFEE` is invalid because EIP-1559 is not supported. Make sure you're not using `BASEFEE` or `block.basefee` in solidity.

### EVM Precompiles

The `RIPEMD-160` (address `0x3`), `blake2f` (address `0x9`) are currently not supported. Calls to unsupported precompiled contracts will revert. These precompiles are rarely used—`RIPEMD-160`, for example, has been [called a total of \~2,600 times](https://etherscan.io/txsInternal?a=0x0000000000000000000000000000000000000003\&m=advanced) *since the inception of Ethereum.*

The other EVM precompiles are well supported.

### zkEVM State Trie <a href="#zkevm-state-trie" id="zkevm-state-trie"></a>

There are some differences between the Merlin zkEVM Merkle tree and EVM Merkle tree.

A zkEVM state is stored in the form of a Sparse Merkle Tree (SMT), which is a binary tree. Instead of *Keccak-256*, the `POSEIDON` Hash Function is used to build the SMTs, mainly due to its STARK-friendliness.

It is important to note that unlike the EVM tree, the zkEVM SMT does not add all the parameters in one leaf of the Merkle tree.

For convenience and achieving faster computations, each of the parameters (the nonce, balance, storage root and code hash) is stored in its respective leaf.

An additional parameter called `codeHashLen` is used to store the length of the Code hash. A fifth leaf-type is used for this zkEVM-specific parameter.

Also, each value in a leaf is an array of eight values, \[V0,V1,V2,…,V7], where each Vi is a 32-bit element. That field is the Goldilocks prime field 𝐹𝑝 where 𝑝=2^64−2^32+1.

The 32-bit field elements are 8 in number, so as to be compatible with the 256-bit EVM words.

So although in the EVM context computation work with 256-bit words, internally the zkEVM uses 8 times 32-bit field elements.

Each of the values; V0,V1,V2,…,V7; is composed of the 32 less significant bits of the 63.99-bit Goldilocks prime field elements.

The figure below depicts the 5 leaf-types together with the corresponding keys:

![A simplified zkEVM's state trie](https://docs.polygon.technology/img/zkEVM/07msm-zkevm-state-trie.png)

### Block Interval

Merlin aims for a constant block interval of 3 seconds.  While it's 12 seconds in Ethereum under ideal conditions. Having a faster, constant block interval results in quicker feedback and a better user experience.

When the load is high, the block interval may slightly exceed 3 seconds, for example, 4 seconds.

When the last block of the previous batch contains fewer transactions, the timestamp of the next block may be the same, resulting in a block interval of 0 seconds.

Otherwise, a constant block interval of 3 seconds is ensured.

### Transaction Fees

The fee structure in Merlin doesn't support EIP-1559.

In Merlin, developers had to specify a **gasPrice** value to send a transaction. After EIP-1559, the **gasPrice** parameter is replaced by **maxFeePerGas** and **maxPriorityFeePerGas**.

* **maxFeePerGas** is the maximum amount of gas fee a user is willing to pay per unit of gas for a transaction.
* **maxPriorityFeePerGas** is an optional fee that is set by the user. Using this variable, users may pay a premium for a high-priority transaction. Whenever a block reaches 100% capacity, this parameter determines transaction priority, the same as before EIP-1559.

Consider changing to a `gasPrice` value when `maxFeePerGas` and `maxPriorityFeePerGas` were used.

### Sending Native Token (transfer, send, call)

There's no difference between Ethereum and Merlin sending native token(ETH in Ethereum or BTC in Merlin). However we strongly recommend not using some methods supported.

You can send native token to others by

* `transfer` (2300 gas, throws error)
* `send` (2300 gas, returns bool)
* `call` (forward all gas or set gas, returns bool)

`call` in combination with re-entrancy guard is the only recommended method to use.&#x20;

Though supported, `transfer` and `send` are not recommended to use. 2300 gas will cause serious problems like [upgradeable contract cannot be receiver](https://forum.openzeppelin.com/t/openzeppelin-upgradeable-contracts-affected-by-istanbul-hardfork/1616).


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.merlinchain.io/merlin-docs/developers/ethereum-and-merlin-differences.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
