## Keyboard shortcuts

Press `←` or `→` to navigate between chapters

Press `S` or `/` to search in the book

Press `?` to show this help

Press `Esc` to hide this help

# Differences to EVM

This section highlights some potentially observable differences in the YUL EVM dialect translation compared to Ethereum Solidity.

Solidity developers deploying dApps to `pallet-revive` ought to read and understand this section well.

## Deploy code vs. runtime code

Our contract runtime does not differentiate between runtime code and deploy (constructor) code. Instead, both are emitted into a single PVM contract code blob and live on-chain. Therefore, in EVM terminology, the deploy code equals the runtime code.

> Tip

> In constructor code, the `codesize` instruction will return the call data size instead of the actual code blob size.

## Solidity

We are aware of the following differences in the translation of Solidity code.

### `address.creationCode`

This returns the bytecode keccak256 hash instead.

## YUL functions

The below list contains noteworthy differences in the translation of YUL functions.

> Note

> Many functions receive memory buffer offset pointer or size arguments. Since the PVM pointer size is 32 bit, supplying memory offset or buffer size values above `2^32-1` will trap the contract immediately.

The `solc` compiler ought to always emit valid memory references, so Solidity dApp authors don’t need to worry about this unless they deal with low level `assembly` code.

### `mload`, `mstore`, `msize`, `mcopy` (memory related functions)

In general, revive preserves the memory layout, meaning low level memory operations are supported. However, a few caveats apply:

- The EVM linear heap memory is emulated using a fixed byte buffer of 64kb. This implies that the maximum memory a contract can use is limited to 64kbit (on Ethereum, contract memory is capped by gas and therefore varies).
- Thus, accessing memory offsets larger than the fixed buffer size will trap the contract at runtime with an `OutOfBound` error.
- The compiler might detect and optimize unused memory reads and writes, leading to a different `msize` compared to what the EVM would see.

### `calldataload`, `calldatacopy`

In the constructor code, the offset is ignored and this always returns `0`.

### `codecopy`

Only supported in constructor code.

### `invalid`

Traps the contract but does not consume the remaining gas.

### `create`, `create2`

Deployments on revive work different than on EVM. In a nutshell: Instead of supplying the deploy code concatenated with the constructor arguments (the EVM deploy model), the revive runtime expects two pointers:

1. A buffer containing the code hash to deploy.
2. The constructor arguments buffer.

To make contract instantiation using the `new` keyword in Solidity work seamlessly, `revive` translates the `dataoffset` and `datasize` instructions so that they assume the contract hash instead of the contract code. The hash is always of constant size. Thus, `revive` is able to supply the expected code hash and constructor arguments pointer to the runtime.

> Warning

> This might fall apart in code creating contracts inside `assembly` blocks. We strongly discourage using the `create` family opcodes to manually craft deployments in `assembly` blocks! Usually, the reason for using `assembly` blocks is to save gas, which is futile on revive anyways due to lower transaction costs.

### `dataoffset`

Returns the contract hash.

### `datasize`

Returns the contract hash size (constant value of `32`).

### `prevrandao`, `difficulty`

Translates to a constant value of `2500000000000000`.

### `pc`, `extcodecopy`

Only valid to use in EVM (they also have no use case in PVM) and produce a compile time error.

### `blobhash`, `blobbasefee`

Related to the Ethereum rollup model and produce a compile time error. Polkadot offers a superior rollup model, removing the use case for blob data related opcodes.

## Difference regarding the `solc` `via-ir` mode

There are two different compilation pipelines available in `solc` and there are small differences between them.

Since `resolc` processes the YUL IR, always assume the `solc` IR based codegen behavior for contracts compiled with the `revive` compiler.