neo-devpack-solidity 0.22.0

Production-focused Solidity-to-NeoVM compilation system
Documentation
---
title: "EIP-2718 — Typed Transaction Envelope"
description: "EIP-2718 — Typed Transaction Envelope mapped to Neo N3."
---

# EIP-2718 — Typed Transaction Envelope

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

<StandardsMirror>

<StandardEntry
  id="eip-2718"
  title="EIP-2718 — Typed Transaction Envelope"
  eip="2718"
  status="Final"
  neoMapping="Native single transaction type"
  category="Transactions"
  parityLabel="Native"
  parityClass="sm-pill-native"
>

<template #spec>

## EIP-2718: Typed Transaction Envelope

Originally, Ethereum had one transaction format. [EIP-2930](./eip-2930) (access lists) and
[EIP-1559](./eip-1559) (base fee) needed new fields, but breaking the existing format would have
required a hard fork. EIP-2718 introduces a **type byte** as the first byte of
serialised transactions:

| Type | Defined by |
| --- | --- |
| `0xc0`-`0xfe` | Legacy (RLP-encoded transaction directly) |
| `0x00` | Reserved |
| `0x01` | [EIP-2930]./eip-2930 (access list) |
| `0x02` | [EIP-1559]./eip-1559 (fee market) |
| `0x03` | [EIP-4844]./eip-4844 (blob) |
| `0x04` | [EIP-7702]/standards-mirror/account-and-auth/eip-7702 (set-code) |

### Neo Equivalent

Neo has a single transaction type by design. Adding new capabilities (access lists
via witness scopes, fee handling, etc.) is done by **extending the existing
transaction structure**. Backward compatibility is handled at the network protocol
level rather than by introducing parallel formats. The serialisation is binary,
versioned by the network message version.


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

| Implementation | Contract Hash | Deploy Tx |
| --- | --- | --- |
| **Solidity** (`neo-solc`) | `0x4e2300b8426b26eb8bbf57398a53ad810e313bf6` | [`0x3f88a613…63d867`]https://dora.coz.io/transaction/neo3/testnet/0x3f88a613436f0ed9e6674037787d841564e7b14e0acaaca29b0674310663d867 |
| **Neo C#** (`nccs`) | `0xb600afb3c034ff11a3e25a26fa03b58e263d9cb8` | [`0x989908a1…c2ed1f`]https://dora.coz.io/transaction/neo3/testnet/0x989908a192be330bb6e5b642f1080c43b71be17e3528e42ccef320e4a2c2ed1f |

Checked-in snapshot: Solidity 3 / 3 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-2718/`](https://github.com/r3e-network/neo-devpack-solidity/tree/main/docs/standards-mirror/deployments/eip-2718).
:::

</template>

<template #solidity>

```solidity
// EIP-2718 type-prefixed serialisation example:
//
//   serialized_tx = type_byte || rlp([type-specific fields])
//
// Wallets must know how to construct each type. EIP-1559 (type 0x02):
//
//   0x02 || rlp([
//     chainId, nonce, maxPriorityFeePerGas, maxFeePerGas,
//     gasLimit, to, value, data, accessList, v, r, s
//   ])
//
// Type 0x03 (blob, EIP-4844):
//
//   0x03 || rlp([
//     chainId, nonce, maxPriorityFeePerGas, maxFeePerGas,
//     gasLimit, to, value, data, accessList,
//     maxFeePerBlobGas, blobVersionedHashes,
//     v, r, s
//   ])
//
// Each new EIP adds another type. Wallets, indexers, RPC clients all need to
// support every type they want to handle.
```

</template>

<template #csharp>

```csharp
// Neo's transaction shape (one type):
//
//   class Transaction {
//     byte Version;           // network version
//     uint Nonce;
//     long SystemFee;
//     long NetworkFee;
//     uint ValidUntilBlock;
//     Signer[] Signers;       // up to 16 signers, each with scopes
//     TransactionAttribute[] Attributes;  // OracleResponse, HighPriority, etc.
//     byte[] Script;          // VM bytecode to execute
//     Witness[] Witnesses;    // one per Signer, in same order
//   }
//
// New capabilities are added via:
//   - Bumping Version
//   - Adding new TransactionAttribute kinds
//   - Adding new Signer scope flags
//
// All fields are present in every transaction. There's no parallel format —
// older nodes simply reject transactions whose Version they don't support.

using Neo;
using Neo.SmartContract.Framework;
using Neo.SmartContract.Framework.Attributes;
using Neo.SmartContract.Framework.Native;

namespace R3E.Examples;

[DisplayName("TxIntrospection")]
public class TxIntrospection : SmartContract
{
    /// <summary>Read transaction-level fields available to any contract during execution.</summary>
    public static (uint, ulong, ulong, byte) CurrentTx()
    {
        var tx = (Transaction)Runtime.ScriptContainer;
        return (tx.ValidUntilBlock, (ulong)tx.SystemFee, (ulong)tx.NetworkFee, tx.Version);
    }
}
```

</template>

</StandardEntry>

</StandardsMirror>