Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
9d2855f
latest eip7702 wip
rakita Aug 7, 2024
bd2f4ee
add code loading handler
rakita Aug 7, 2024
6fa2fb0
WIP adding is_delegate_cold flag
rakita Aug 8, 2024
5020d9f
feat: add StateLoad and Eip7702CodeLoad
rakita Aug 9, 2024
5db4074
feat: add gas accounting among other things
rakita Aug 9, 2024
6a91562
clippy,fmt, op test
rakita Aug 9, 2024
9e3735b
Merge remote-tracking branch 'origin/main' into eip7702
rakita Aug 9, 2024
05940a8
Merge remote-tracking branch 'origin/main' into eip7702
rakita Aug 9, 2024
cab9bb1
path to latest alloy-eips
rakita Aug 9, 2024
43918ca
comment eip7702 decode tests
rakita Aug 9, 2024
a466e2f
Eip7702 format starts with 0xEF0100
rakita Aug 10, 2024
16c3933
typo
rakita Aug 10, 2024
18548c5
fix(eip7702): fix empty or eip7702 code check
rkrasiuk Aug 15, 2024
e665984
Merge pull request #1705 from bluealloy/rkrasiuk/fix-empty-and-eip770…
rkrasiuk Aug 15, 2024
9efccc4
Type Eip7702s to Eip7702
rakita Aug 15, 2024
b9b8f27
Corrent comments
rakita Aug 15, 2024
071e285
switch new and new_raw Eip7702Bytecode
rakita Aug 15, 2024
a69e173
propagate last commit
rakita Aug 15, 2024
7c4196d
nit: rename fn
rakita Aug 15, 2024
7e3c47d
fix(eip7702): set delegated code on call (#1706)
rkrasiuk Aug 15, 2024
d2111c6
type change, return eip7702 raw on Bytecode::bytecode
rakita Aug 15, 2024
caadc71
eip7702 delegation test
rakita Aug 15, 2024
502d6d1
Cleanup, refactor sstore gas calc
rakita Aug 27, 2024
6e7868c
doc
rakita Aug 27, 2024
2609442
chore: add AuthList json format
rakita Aug 27, 2024
2b5331f
fix initial eip7702 gas, fix eip7702 refund on revert
rakita Aug 27, 2024
61b3567
small refactor
rakita Aug 27, 2024
3098302
fix refund cnt
rakita Aug 27, 2024
54a21a6
error handling, EIP-3607 fix, wip on auth validity
rakita Aug 28, 2024
53d4143
add auth validity check, fix EIP-3607 fix
rakita Aug 28, 2024
f56ff19
Merge remote-tracking branch 'origin/main' into eip7702
rakita Aug 28, 2024
1cec60d
switch tests
rakita Aug 28, 2024
c427b99
missing comment
rakita Aug 28, 2024
af5e112
fix tests
rakita Aug 28, 2024
7a2a01c
rm println
rakita Aug 28, 2024
9db723e
remove skip of required fields
rakita Aug 28, 2024
4add28b
docs, test meta dat
rakita Aug 29, 2024
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
Prev Previous commit
Next Next commit
Eip7702 format starts with 0xEF0100
  • Loading branch information
rakita committed Aug 10, 2024
commit a466e2fb65f8dc4e1ba07f0d62739ebb9a88329f
4 changes: 2 additions & 2 deletions bins/revme/src/cmd/evmrunner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use revm::{
db::BenchmarkDB,
inspector_handle_register,
inspectors::TracerEip3155,
primitives::{eof::EofDecodeError, Address, Bytecode, TxKind},
primitives::{Address, Bytecode, BytecodeDecodeError, TxKind},
Evm,
};
use std::io::Error as IoError;
Expand All @@ -26,7 +26,7 @@ pub enum Errors {
#[error(transparent)]
Io(#[from] IoError),
#[error(transparent)]
EofError(#[from] EofDecodeError),
BytecodeDecodeError(#[from] BytecodeDecodeError),
}

/// Evm runner command allows running arbitrary evm bytecode.
Expand Down
51 changes: 42 additions & 9 deletions crates/primitives/src/bytecode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ pub mod legacy;
pub use eof::{Eof, EOF_MAGIC, EOF_MAGIC_BYTES, EOF_MAGIC_HASH};
pub use legacy::{JumpTable, LegacyAnalyzedBytecode};

use crate::{keccak256, Bytes, Eip7702Bytecode, B256, KECCAK_EMPTY};
use crate::{keccak256, Bytes, Eip7702Bytecode, B256, EIP7702_MAGIC_BYTES, KECCAK_EMPTY};
use alloy_primitives::Address;
use core::panic;
use core::{fmt::Debug, panic};
use eof::EofDecodeError;
use std::sync::Arc;
use std::{fmt, sync::Arc};

/// State of the [`Bytecode`] analysis.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
Expand Down Expand Up @@ -102,12 +102,18 @@ impl Bytecode {
///
/// Returns an error on incorrect EOF format.
#[inline]
pub fn new_raw_checked(bytecode: Bytes) -> Result<Self, EofDecodeError> {
// TODO include EIP-7702 check
if bytecode.starts_with(&EOF_MAGIC_BYTES) {
Ok(Self::Eof(Arc::new(Eof::decode(bytecode)?)))
} else {
Ok(Self::LegacyRaw(bytecode))
pub fn new_raw_checked(bytecode: Bytes) -> Result<Self, BytecodeDecodeError> {
let prefix = bytecode.get(..2);
match prefix {
Some(prefix) if prefix == &EOF_MAGIC_BYTES => {
let eof = Eof::decode(bytecode)?;
Ok(Self::Eof(Arc::new(eof)))
}
Some(prefix) if prefix == &EIP7702_MAGIC_BYTES => {
let eip7702 = Eip7702Bytecode::new(bytecode).ok_or(BytecodeDecodeError::Eip7702)?;
Ok(Self::Eip7702s(eip7702))
}
_ => Ok(Self::LegacyRaw(bytecode)),
}
}

Expand Down Expand Up @@ -207,6 +213,33 @@ impl Bytecode {
}
}

/// EOF decode errors.
#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum BytecodeDecodeError {
Eof(EofDecodeError),
// TODO EIP-7702 add errors
Eip7702,
}

impl From<EofDecodeError> for BytecodeDecodeError {
fn from(error: EofDecodeError) -> Self {
Self::Eof(error)
}
}

#[cfg(feature = "std")]
impl std::error::Error for BytecodeDecodeError {}

impl fmt::Display for BytecodeDecodeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Eof(e) => fmt::Display::fmt(e, f),
Self::Eip7702 => f.write_str("EIP-7702 decode error"),
}
}
}

#[cfg(test)]
mod tests {
use super::{Bytecode, Eof};
Expand Down
1 change: 1 addition & 0 deletions crates/primitives/src/bytecode/eof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ impl Eof {

/// EOF decode errors.
#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum EofDecodeError {
/// Short input while processing EOF.
MissingInput,
Expand Down
2 changes: 1 addition & 1 deletion crates/primitives/src/eip7702.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pub mod bytecode;
pub use authorization_list::{
Authorization, AuthorizationList, RecoveredAuthorization, Signature, SignedAuthorization,
};
pub use bytecode::{Eip7702Bytecode, EIP7702_MAGIC, EIP7702_MAGIC_BYTES};
pub use bytecode::{Eip7702Bytecode, EIP7702_MAGIC, EIP7702_MAGIC_BYTES, EIP7702_VERSION};

// Base cost of updating authorized account.
pub const PER_AUTH_BASE_COST: u64 = 2500;
Expand Down
12 changes: 12 additions & 0 deletions crates/primitives/src/eip7702/authorization_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,18 @@ impl AuthorizationList {
}
}

/// Returns true if the authorization list is valid.
/// TODO EIP-7702 switch to error type.
pub fn is_valid(&self) -> bool {
true
/*
match self {
Self::Signed(signed) => signed.iter().all(|signed| signed.is_valid()),
Self::Recovered(recovered) => recovered.iter().all(|recovered| recovered.is_valid()),
}
*/
}

/// Return empty authorization list.
pub fn empty() -> Self {
Self::Recovered(Vec::new())
Expand Down
32 changes: 25 additions & 7 deletions crates/primitives/src/eip7702/bytecode.rs
Original file line number Diff line number Diff line change
@@ -1,40 +1,57 @@
use crate::{bytes, Address, Bytes};

/// EIP Version Magic in u16 form.
/// EIP-7702 Version Magic in u16 form.
pub const EIP7702_MAGIC: u16 = 0xEF01;

/// EOF magic number in array form.
/// EIP-7702 magic number in array form.
pub static EIP7702_MAGIC_BYTES: Bytes = bytes!("ef01");

/// EIP-7702 first version of bytecode.
pub const EIP7702_VERSION: u8 = 0;

/// Bytecode of delegated account, specified in EIP-7702
///
/// Format of EIP-7702 bytecode consist of:
/// 0xEF00 (MAGIC) + 0x00 (VERSION) + 20 bytes of address.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Eip7702Bytecode {
pub delegated_address: Address,
pub version: u8,
pub raw: Bytes,
}

impl Eip7702Bytecode {
/// Creates a new EIP-7702 bytecode or returns None if the raw bytecode is invalid.
#[inline]
pub fn new(raw: Bytes) -> Option<Self> {
if raw.len() != 22 {
if raw.len() != 23 {
return None;
}
if !raw.starts_with(&EIP7702_MAGIC_BYTES) {
return None;
}

// Only suported version is version 0.
if raw[2] != EIP7702_VERSION {
return None;
}

Some(Self {
delegated_address: Address::new(raw[2..].try_into().unwrap()),
delegated_address: Address::new(raw[3..].try_into().unwrap()),
version: EIP7702_VERSION,
raw,
})
}

/// Creates a new EIP-7702 bytecode with the given address.
pub fn new_address(address: Address) -> Self {
let mut raw = EIP7702_MAGIC_BYTES.to_vec();
raw.push(EIP7702_VERSION);
raw.extend(&address);
Self {
delegated_address: address,
version: EIP7702_VERSION,
raw: raw.into(),
}
}
Expand All @@ -60,12 +77,13 @@ mod tests {
fn sanity_decode() {
let raw = bytes!("ef01deadbeef");
assert_eq!(Eip7702Bytecode::new(raw), None);
let raw = bytes!("ef01deadbeef00000000000000000000000000000000");
let address = raw[2..].try_into().unwrap();
let raw = bytes!("ef0100deadbeef00000000000000000000000000000000");
let address = raw[3..].try_into().unwrap();
assert_eq!(
Eip7702Bytecode::new(raw.clone()),
Some(Eip7702Bytecode {
delegated_address: address,
version: 0,
raw,
})
);
Expand All @@ -78,7 +96,7 @@ mod tests {
assert_eq!(bytecode.delegated_address, address);
assert_eq!(
bytecode.raw,
bytes!("ef010101010101010101010101010101010101010101")
bytes!("ef01000101010101010101010101010101010101010101")
);
}
}
5 changes: 5 additions & 0 deletions crates/primitives/src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,11 @@ impl Env {
return Err(InvalidTransaction::EmptyAuthorizationList);
}

// Check validity of authorization_list
if !auth_list.is_valid() {
return Err(InvalidTransaction::InvalidAuthorizationList);
}

// Check if other fields are unset.
if self.tx.max_fee_per_blob_gas.is_some() || !self.tx.blob_hashes.is_empty() {
return Err(InvalidTransaction::AuthorizationListInvalidFields);
Expand Down
3 changes: 3 additions & 0 deletions crates/primitives/src/result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,8 @@ pub enum InvalidTransaction {
AuthorizationListInvalidFields,
/// Empty Authorization List is not allowed.
EmptyAuthorizationList,
/// Invalid EIP-7702 Authorization List
InvalidAuthorizationList,
/// Optimism-specific transaction validation error.
#[cfg(feature = "optimism")]
OptimismError(OptimismInvalidTransaction),
Expand Down Expand Up @@ -396,6 +398,7 @@ impl fmt::Display for InvalidTransaction {
write!(f, "authorization list tx has invalid fields")
}
Self::EmptyAuthorizationList => write!(f, "empty authorization list"),
Self::InvalidAuthorizationList => write!(f, "invalid authorization list"),
#[cfg(feature = "optimism")]
Self::OptimismError(op_error) => op_error.fmt(f),
}
Expand Down