Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 18 additions & 15 deletions EVM.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ Implemented in this workspace:
creating or funding the corresponding EVM-native purse identity.
- [EIP-7702][eip-7702] type `0x04` set-code transactions, with authorization
lists passed through to `revm` for Prague execution.
- [EIP-4788][eip-4788] beacon roots predeploy, native pre-block state update,
and native direct-call lookup. Casper stores the parent Casper block hash as
the root value.
- [EIP-4788][eip-4788] beacon roots predeploy with a native direct-call
shortcut that returns a zero root. Casper does not support beacon-root
history or pre-block state updates.
- [EIP-2935][eip-2935] block-hash history predeploy and native direct-call
lookup backed by indexed Casper block headers.

Expand All @@ -80,7 +80,8 @@ Implemented in the sidecar workspace for validation:
- `eth_getTransactionReceipt` projects logs stored in
`ExecutionResult::Evm` as Ethereum receipt log entries.
- `eth_getBlockByNumber` projects `parentBeaconBlockRoot` as the parent Casper
block hash, matching Casper's [EIP-4788][eip-4788] system-contract value.
block hash. This sidecar projection is independent of the zero-valued
[EIP-4788][eip-4788] contract shortcut.
- Development-only Cargo patches pointing sidecar at this node workspace for
unreleased `casper-types` and `casper-binary-port` changes.

Expand All @@ -107,7 +108,7 @@ Ethereum JSON-RPC method names below refer to the Ethereum
| `EvmSpec::Prague` / `revm::SpecId::PRAGUE` | Implemented. | Execution behavior is delegated to `revm`; Casper does not maintain its own EVM interpreter. |
| [EIP-2537][eip-2537] BLS12-381 precompiles | Delegated to `revm`. | Expected at `0x0b` through `0x11`, but Casper-owned conformance tests are still needed for gas costs, malformed input, subgroup checks, and failure behavior. |
| [EIP-2935][eip-2935] block-hash history contract | Implemented with Casper storage semantics. | The standard address, bytecode, and 8191-block interface are present, but direct calls read indexed LMDB block headers instead of Merkleized contract storage. There is no pre-block system call or gradual ring-buffer fill. |
| [EIP-4788][eip-4788] beacon roots contract | Implemented. | The standard address, bytecode, and interface are present. Casper writes and reads the parent Casper block hash natively through block-global state rather than executing the predeploy bytecode. |
| [EIP-4788][eip-4788] beacon roots contract | Intentionally unsupported (non-goal). | The standard address and bytecode are present, but direct `CALL` and `STATICCALL` lookups are intercepted and always return an all-zero root. Casper does not write beacon-root history. Do not treat this product decision as an open compatibility gap. |
| [EIP-6110][eip-6110] validator deposit requests | Missing / decision needed. | Ethereum-specific deposit-log-to-request flow. Full support requires [EIP-7685][eip-7685] request construction and commitment. |
| [EIP-7002][eip-7002] withdrawal request predeploy | Missing / decision needed. | Contract-visible predeploy at `0x00000961Ef480Eb55e80D19ad83579A64c007002` is absent. Full support requires queue/fee state, post-block extraction, and [EIP-7685][eip-7685] request output. |
| [EIP-7251][eip-7251] consolidation request predeploy | Missing / decision needed. | Contract-visible predeploy at `0x0000BBdDc7CE488642fb579F8B00f3a590007251` is absent. Full support has the same request-output dependency as EIP-7002. |
Expand Down Expand Up @@ -136,7 +137,7 @@ Ethereum JSON-RPC method names below refer to the Ethereum
| `NUMBER`, `TIMESTAMP`, `GASLIMIT`, `BASEFEE` | Implemented. | Timestamp is Casper block time in seconds. Base fee is chainspec-configured and wei-denominated through `wei_per_mote`, not Ethereum's dynamic base-fee adjustment. |
| `COINBASE` | Implemented with Casper semantics. | The address is derived from the Casper block proposer public key. |
| `CHAINID` | Implemented. | Transaction chain ID is enforced against chainspec `[evm].chain_id`. |
| `PREVRANDAO` | Weak / missing semantic mapping. | Casper does not plumb a randomness field into the EVM block context, so contracts should not treat it as Ethereum beacon randomness. |
| `PREVRANDAO` | Implemented with Casper semantics. | The value is derived from the parent Casper block's accumulated seed. It provides Casper randomness, not Ethereum beacon-chain RANDAO semantics. |
| `BLOBHASH` and blob-related block context | Missing / misleading. | No accepted blob transactions means no meaningful blob versioned hashes, blob gas, or blob fee context. |
| Fee charging | Casper-specific. | `revm` fee charging is disabled; Casper hold, refund, and fee accounting owns balance effects according to the chainspec. |

Expand Down Expand Up @@ -181,26 +182,28 @@ executor.
previous Cancun/Dencun upgrade. It is included in this review because a Prague
Ethereum-compatible environment has this contract. In this branch, Casper
installs the exact EIP-4788 runtime bytecode at
`0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02`, writes the parent hash natively
before user transactions, and serves direct calls through the Casper
precompile provider. It uses:
`0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02`. Direct `CALL` and `STATICCALL`
lookups are intercepted by the Casper precompile provider and currently
return:

```text
parentBeaconBlockRoot := parent Casper block hash
parentBeaconBlockRoot := 0x0000000000000000000000000000000000000000000000000000000000000000
```

This gives contracts a deterministic consensus-root oracle for Casper. It is
not strict Ethereum beacon-chain semantics. The detailed, audited compatibility
matrix is in [Current Status](#current-status).
Casper does not support Ethereum beacon-chain roots, run the EIP-4788 pre-block
system call, or persist its ring buffer. The zero-valued response is not strict
EIP-4788 semantics. This is an intentional product non-goal, not an open gap;
revisit it only if the product decision changes. The detailed, audited
compatibility matrix is in [Current Status](#current-status).

Casper installs the exact EIP-2935 runtime bytecode at
`0x0000F90827F1C53a10cb7A02335B175320002935`. Direct `CALL` and `STATICCALL`
lookups are intercepted natively and read indexed Casper block headers through
the data access layer. Casper does not execute an EIP-2935 block-boundary
system call or populate the standard contract-storage ring.

The highest-priority smart-contract-visible gaps after EIP-4788 and EIP-2935
are request predeploy decisions for [EIP-7002][eip-7002] and
The highest-priority smart-contract-visible gaps are request predeploy
decisions for [EIP-7002][eip-7002] and
[EIP-7251][eip-7251], and explicit Prague conformance coverage for
[EIP-2537][eip-2537], [EIP-7623][eip-7623], and [EIP-7702][eip-7702].

Expand Down
8 changes: 4 additions & 4 deletions execution_engine_testing/tests/src/test/explorer/faucet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -663,14 +663,14 @@ fn faucet_costs() {
// This test will fail if execution costs vary. The expected costs should not be updated
// without understanding why the cost has changed. If the costs do change, it should be
// reflected in the "Costs by Entry Point" section of the faucet crate's README.md.
const EXPECTED_FAUCET_INSTALL_COST: u64 = 119_810_320_929;
const EXPECTED_FAUCET_INSTALL_COST: u64 = 118_807_845_390;
const EXPECTED_FAUCET_INSTALL_COST_ALT: u64 = 149_230_872_143;

const EXPECTED_FAUCET_SET_VARIABLES_COST: u64 = 79_749_265;
const EXPECTED_FAUCET_SET_VARIABLES_COST: u64 = 79_790_440;

const EXPECTED_FAUCET_CALL_BY_INSTALLER_COST: u64 = 2_652_913_398;
const EXPECTED_FAUCET_CALL_BY_INSTALLER_COST: u64 = 2_652_954_573;

const EXPECTED_FAUCET_CALL_BY_USER_COST: u64 = 2_558_746_881;
const EXPECTED_FAUCET_CALL_BY_USER_COST: u64 = 2_558_820_996;

let installer_account = AccountHash::new([1u8; 32]);
let user_account: AccountHash = AccountHash::new([2u8; 32]);
Expand Down
33 changes: 0 additions & 33 deletions executor/evm/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use casper_storage::{
data_access_layer::DataAccessLayer,
eip2935,
global_state::{error::Error as GlobalStateError, state::StateReader},
tracking_copy::TrackingCopyExt,
TrackingCopy,
};
use casper_types::{evm, CLValue, EvmAddr, Key, StoredValue, U512};
Expand Down Expand Up @@ -92,38 +91,6 @@ where
};
self.block_hash_at_height(requested_height).map(Some)
}

/// Executes the native EIP-4788 `get` operation.
///
/// The lookup is backed only by the current tracking copy; EVM execution must not depend on
/// locally retained block history.
pub(crate) fn eip4788_get(&mut self, input: &[u8]) -> Result<Option<B256>, DbError> {
// EIP-4788 accepts one uint256 timestamp. Values wider than u64 must revert rather
// than truncate to a colliding ring-buffer timestamp.
if input.len() != 32 || input[..24].iter().any(|byte| *byte != 0) {
return Ok(None);
}

let timestamp = u64::from_be_bytes(
input[24..]
.try_into()
.expect("the final 8 bytes of a 32-byte input have fixed length"),
);
if timestamp == 0 {
return Ok(None);
}

let Some((stored_timestamp, block_hash)) =
self.tracking_copy.get_eip4788_parent_hash(timestamp)?
else {
return Ok(None);
};
if stored_timestamp != timestamp {
return Ok(None);
}

Ok(Some(tx::to_revm_block_hash(block_hash)))
}
}

impl<R, S> Database for CasperDb<'_, R, S>
Expand Down
14 changes: 8 additions & 6 deletions executor/evm/src/precompiles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,14 @@ where
&& inputs.bytecode_address == beacon_roots_address
&& matches!(inputs.scheme, CallScheme::Call | CallScheme::StaticCall)
{
// Copy the input before borrowing the database mutably. The input may be backed by
// revm's shared memory buffer.
let input = inputs.input.bytes(context);
let lookup_result = context.db_mut().eip4788_get(&input);
let result =
native_get_result(context, lookup_result, inputs.gas_limit, inputs.reservoir);
// Casper does not support Ethereum beacon-chain roots. Keep the predeploy callable
// without maintaining placeholder state.
let result = native_get_result(
context,
Ok(Some(B256::ZERO)),
inputs.gas_limit,
inputs.reservoir,
);
return Ok(Some(result));
}

Expand Down
1 change: 1 addition & 0 deletions executor/evm/src/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ pub struct BlockContext {
///
/// Defaults to chainspec `[evm].base_fee * [evm].wei_per_mote`.
pub base_fee: Option<u128>,
/// Casper parent-block accumulated seed exposed through the `PREVRANDAO` opcode.
pub prevrandao: evm::Hash,
}

Expand Down
Loading
Loading