neo-devpack-solidity 0.22.0

Production-focused Solidity-to-NeoVM compilation system
Documentation
---
title: "EIP-3855 — PUSH0 Opcode"
description: "EIP-3855 — PUSH0 Opcode mapped to Neo N3."
---

# EIP-3855 — PUSH0 Opcode

[Back to Protocol-Level EIPs](/standards-mirror/protocol-eips)

<StandardsMirror>

<StandardEntry
  id="eip-3855"
  title="EIP-3855 — PUSH0 Opcode"
  eip="3855"
  status="Final"
  neoMapping="Native PUSH0 in NeoVM"
  category="Opcodes"
  parityLabel="Native"
  parityClass="sm-pill-native"
>

<template #spec>

## EIP-3855: PUSH0 Opcode

Before EIP-3855, pushing zero onto the EVM stack required `PUSH1 0x00` (2 bytes,
3 gas). EIP-3855 added `PUSH0` (`0x5f`) — 1 byte, 2 gas. A trivial-looking change
that saves significant bytecode size and gas across the entire ecosystem because
zero is the most-pushed value.

### Status

Activated in the Shanghai hard fork (April 2023). Solidity 0.8.20+ emits PUSH0 by
default for chains that support it.

### Neo Equivalent

NeoVM has had `PUSH0` (opcode `0x10`) since launch, plus `PUSH1` through `PUSH16` as
direct integer constants. There was no need for a retrofit because the design
included it from day one.


::: tip Live on Neo TestNet
Both implementations are deployed on Neo N3 TestNet (network magic `894710606`).

| Implementation | Contract Hash | Deploy Tx |
| --- | --- | --- |
| **Solidity** (`neo-solc`) | `0x52b860448a5d1ff537160a0bee8c83cdfe72fe4d` | [`0xba96b7c4…1c0a8d`]https://dora.coz.io/transaction/neo3/testnet/0xba96b7c4398ed9d881c0a789b9222059ae2bba193dc20fc6327f8ead2b1c0a8d |
| **Neo C#** (`nccs`) | `0x6704d604997959ce4e098bd96ecbacef358e9ff6` | [`0x92572481…a6c00c`]https://dora.coz.io/transaction/neo3/testnet/0x925724819e4e732f7bc33eb652acb633a2a08ccd98b5646413e832bdc7a6c00c |

Checked-in snapshot: Solidity 2 / 2 assertions pass; Neo C# 2 / 2 assertions pass. This is a validation snapshot, not an all-green parity certification; see [TestNet Results](/standards-mirror/deployments/RESULTS) for failure details.

Source pairs: [`docs/standards-mirror/deployments/eip-3855/`](https://github.com/r3e-network/neo-devpack-solidity/tree/main/docs/standards-mirror/deployments/eip-3855).
:::

</template>

<template #solidity>

```
EVM bytecode comparison:

Pre-EIP-3855:    60 00     PUSH1 0x00
                 [2 bytes, 3 gas]

Post-EIP-3855:   5f         PUSH0
                 [1 byte, 2 gas]

Across an entire compiled contract, this can save dozens of bytes and millions of
gas across thousands of executions. OZ's ERC-20 dropped ~50 bytes after the
PUSH0 introduction.
```

</template>

<template #csharp>

```
NeoVM bytecode (since day one):

  PUSH0 (0x10)    // push integer 0
  PUSH1 (0x11)    // push integer 1
  PUSH2 (0x12)    // push integer 2
  ...
  PUSH16 (0x20)   // push integer 16

  PUSHM1 (0x0F)   // push integer -1

  PUSHA   (0x0A)  // push address
  PUSHNULL (0x0B) // push StackItem.Null

  PUSHDATA1 (0x0C) ...  // push N bytes (N <= 255)

A Solidity-to-NeoVM compiler (like neo-devpack-solidity) emits PUSH0 directly when it
needs zero. There's no retrofit story here because the VM was designed with
small-integer constant opcodes from the start.
```

### Compiler Note

The `neo-devpack-solidity` compiler maps Solidity zero literals to NeoVM `PUSH0` on every
emit. No version gate, no chain-version conditional — the opcode has always been
available.

</template>

</StandardEntry>

</StandardsMirror>