diff --git a/vips/VIP-255.md b/vips/VIP-255.md new file mode 100644 index 0000000..aa88feb --- /dev/null +++ b/vips/VIP-255.md @@ -0,0 +1,108 @@ +--- +VIP: 255 +Title: Interstellar EVM Upgrade Specification +Description: This VIP defines the specification of the EVM changes to align with the Ethereum Cancun, Prague and Osaka upgrades. +Author: Tony Li (@libotony), Paolo Galli (@paologalligit), Mog Lu (@moglu2017), Pedro Gomes (@otherview) +Discussions: TBC +Category: Core +Status: Draft +CreatedAt: 2026-08-03 +--- + +## Overview + +This VIP specifies the changes required to align the VeChainThor EVM with the Cancun, Prague and Osaka releases of Ethereum. + +These changes form the first part of the Interstellar network upgrade. VeChainThor's EVM currently targets the Ethereum Shanghai release, adopted as part of the Galactica upgrade, see [VIP-242](./VIP-242.md). Interstellar advances the EVM by three Ethereum releases in a single fork. + +The second part of the Interstellar upgrade concerns Ethereum transaction equivalence, and will be specified in a separate VIP. + +## Motivation + +Smart contract tooling, compilers and libraries in the wider ecosystem target recent Ethereum releases. Every release that VeChainThor lags behind increases the friction of deploying an existing Ethereum contract onto VeChainThor, and denies VeChainThor developers primitives that are treated as available elsewhere. Transient storage and `MCOPY` in particular are emitted by current Solidity and Vyper versions, and the BLS12-381 and secp256r1 precompiles are prerequisites for common signature-verification, bridging and passkey use cases. + +Adopting three releases at once keeps the number of consensus-breaking forks low while closing the gap in full. + +## Specification + +Changes included in the Network Upgrade: + +### Opcodes + +- [EIP-1153: Transient storage opcodes](https://eips.ethereum.org/EIPS/eip-1153) — `TLOAD` (`0x5c`) and `TSTORE` (`0x5d`), 100 gas each +- [EIP-5656: MCOPY - Memory copying instruction](https://eips.ethereum.org/EIPS/eip-5656) — `MCOPY` (`0x5e`), 3 gas plus 3 gas per word plus memory expansion +- [EIP-6780: SELFDESTRUCT only in same transaction](https://eips.ethereum.org/EIPS/eip-6780) +- [EIP-7939: Count leading zeros (CLZ) opcode](https://eips.ethereum.org/EIPS/eip-7939) — `CLZ` (`0x1e`), 5 gas + +### Precompiled Contracts + +- [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537) — addresses `0x0b` through `0x11` +- [EIP-7951: Precompile for secp256r1 Curve Support](https://eips.ethereum.org/EIPS/eip-7951) — address `0x0100`, 6900 gas +- [EIP-7823: Set upper bounds for MODEXP](https://eips.ethereum.org/EIPS/eip-7823) — base, exponent and modulus each limited to 1024 bytes +- [EIP-7883: ModExp Gas Cost Increase](https://eips.ethereum.org/EIPS/eip-7883) — minimum 500 gas, multiplier 16 + +### Other + +- [EIP-2935: Serve historical block hashes from state](https://eips.ethereum.org/EIPS/eip-2935) +- [EIP-7825: Transaction Gas Limit Cap](https://eips.ethereum.org/EIPS/eip-7825) — 224 (16,777,216) gas per transaction +- [EIP-7934: RLP Execution Block Size Limit](https://eips.ethereum.org/EIPS/eip-7934) — 8,388,608 bytes (8 MiB) per RLP-encoded block + +All gas constants and precompile addresses are adopted unchanged from the referenced EIPs. + +With these changes VeChainThor adopts the complete set of execution layer EIPs from the Ethereum Osaka upgrade. The remaining Osaka EIPs concern blobs and the Ethereum beacon chain, neither of which has an equivalent on VeChainThor. + +## Deviations from Ethereum + +The following describes where VeChainThor's adoption of the above EIPs differs in observable behaviour from Ethereum. Contract authors porting code between the two networks **MUST** account for these differences. + +### EIP-1153: Transient storage is scoped to a clause + +On Ethereum, transient storage is discarded at the end of the transaction. A VeChainThor transaction carries one or more clauses, each executed as a separate EVM execution. Transient storage is allocated per clause and discarded when that clause completes. + +Transient state therefore **MUST NOT** be assumed to persist between clauses of the same transaction, even though those clauses share a transaction and revert atomically. Reentrancy guards built on `TSTORE` remain sound, as reentrancy occurs within a single clause. + +VeChainThor also has no access lists and no warm or cold state access accounting, having adopted neither EIP-2929 nor EIP-2930. The 100 gas cost of `TLOAD` and `TSTORE` is therefore a flat constant on VeChainThor, rather than a reference to the `WARM_STORAGE_READ_COST` parameter it derives from on Ethereum. + +### EIP-6780: `SELFDESTRUCT` is restricted to the same clause + +Following from the scoping above, the "created in the same transaction" condition of EIP-6780 is evaluated as "created in the same clause". `SELFDESTRUCT` deletes the account only when the contract was created within the clause that destroys it. Otherwise the account is retained and only its balance is transferred. + +Additionally, VeChainThor accounts hold both VET and VTHO. `SELFDESTRUCT` transfers both to the recipient, and the VTHO movement emits a `Transfer` event on the VTHO contract. Consistent with Ethereum, a `SELFDESTRUCT` naming the destroyed contract as its own recipient burns the balance rather than preserving it. + +### EIP-2935: Historical block hashes are served from existing state + +Ethereum maintains a ring buffer of recent block hashes, written by the protocol into the storage of the history contract at the start of every block. + +VeChainThor deploys a contract at the address specified by the EIP, `0x0000F90827F1C53a10cb7A02335B175320002935`, and preserves the EIP's calling convention exactly: calldata is a bare 32-byte big-endian block number with no function selector, the serve window is the most recent 8191 blocks, and every invalid input reverts with empty returndata. Contracts written against EIP-2935 therefore work unchanged. + +The implementation differs in that lookups resolve against the existing `Extension` builtin contract instead of a ring buffer. No per-block state writes are performed, as VeChainThor already retains the necessary history in state. + +The values returned are VeChainThor block IDs, whose leading four bytes encode the block number, and not Ethereum-style Keccak block hashes. This matches the existing behaviour of the `BLOCKHASH` opcode on VeChainThor and is unchanged by this VIP. + +### Blob features are not supported + +VeChainThor does not support blob-carrying transactions, so the features Ethereum introduced alongside them have no applicable meaning and are left unassigned. + +Address `0x0a`, the EIP-4844 KZG point evaluation precompile introduced by Cancun, is intentionally unassigned. The precompile set is otherwise identical to Ethereum's Prague and Osaka sets. + +The `BLOBHASH` (`0x49`) and `BLOBBASEFEE` (`0x4a`) opcodes are likewise unassigned. Contract bytecode compiled for Ethereum releases from Cancun onwards that references either opcode fails with an invalid instruction rather than reading a zero value. + +### Precompile addresses hold code + +No EIP requires the behaviour described here. It is a long-standing VeChainThor convention, applied at every fork that has introduced precompiles, and it is documented here because this upgrade extends it to addresses that previously held no code. + +At the Interstellar block, an inert eight-byte runtime bytecode **MUST** be written to every precompile address, including the eight addresses introduced by this VIP: `0x0b` through `0x11` from EIP-2537 and `0x0100` from EIP-7951. This makes those accounts non-empty in state, so that `CREATE` and `CREATE2` cannot deploy a contract over a precompile address. Because this is a state write, an implementation that omits it will diverge on the state root. + +As a consequence `EXTCODESIZE` on a precompile address returns 8 and `EXTCODEHASH` returns the hash of that bytecode, whereas on Ethereum precompile addresses hold no code and `EXTCODESIZE` returns 0. + +## Security Considerations + +**New cryptographic precompiles.** EIP-2537 and EIP-7951 introduce a significant quantity of new cryptographic code into the consensus-critical path. Both are implemented using the same audited upstream libraries used by Ethereum clients rather than bespoke implementations, and the upgrade carries the corresponding Ethereum test vectors for the BLS12-381 operations, `P256VERIFY`, and the EIP-7823 and EIP-7883 `MODEXP` changes. Subgroup and field-element validation on BLS12-381 inputs is a known source of consensus-splitting bugs and requires that implementations reject malformed points rather than accepting them. + +**Clause-scoped transient storage.** A contract ported from Ethereum that relies on transient storage surviving across what it assumes to be one transaction will observe cleared state at each clause boundary on VeChainThor. Where transient storage carries a security invariant, such as a lock or an accumulated authorisation, that invariant is re-initialised per clause. Authors **MUST** confirm that a cleared value is the safe default for their contract. + +**Clause-scoped `SELFDESTRUCT`.** A contract that creates and destroys a helper contract across separate clauses of one transaction will find the helper retained rather than deleted, since the creation and destruction occur in different clauses. Patterns that depend on an address becoming reusable, or on code disappearing, need to keep creation and destruction within a single clause. + +## Copyright + +Copyright and related rights waived via [CC0](../LICENSE.md).