Skip to content

Commit

Permalink
move eip7702_get_code to utils.rs
Browse files Browse the repository at this point in the history
  • Loading branch information
lima-limon-inc committed Jan 24, 2025
1 parent 1f7f05e commit 73c8301
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 63 deletions.
32 changes: 24 additions & 8 deletions crates/vm/levm/src/opcode_handlers/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,12 @@ impl VM {

let (account_info, address_was_cold) = self.access_account(callee);

let (is_delegation, eip7702_gas_consumed, code_address, bytecode) =
self.eip7702_get_code(callee)?;
let (is_delegation, eip7702_gas_consumed, code_address, bytecode) = eip7702_get_code(
&mut self.cache,
&mut self.db,
&mut self.accrued_substate,
callee,
)?;

let gas_left = current_call_frame
.gas_limit
Expand Down Expand Up @@ -132,8 +136,12 @@ impl VM {

let (_account_info, address_was_cold) = self.access_account(code_address);

let (is_delegation, eip7702_gas_consumed, code_address, bytecode) =
self.eip7702_get_code(code_address)?;
let (is_delegation, eip7702_gas_consumed, code_address, bytecode) = eip7702_get_code(
&mut self.cache,
&mut self.db,
&mut self.accrued_substate,
code_address,
)?;

let gas_left = current_call_frame
.gas_limit
Expand Down Expand Up @@ -239,8 +247,12 @@ impl VM {
calculate_memory_size(return_data_start_offset, return_data_size)?;
let new_memory_size = new_memory_size_for_args.max(new_memory_size_for_return_data);

let (is_delegation, eip7702_gas_consumed, code_address, bytecode) =
self.eip7702_get_code(code_address)?;
let (is_delegation, eip7702_gas_consumed, code_address, bytecode) = eip7702_get_code(
&mut self.cache,
&mut self.db,
&mut self.accrued_substate,
code_address,
)?;

let gas_left = current_call_frame
.gas_limit
Expand Down Expand Up @@ -314,8 +326,12 @@ impl VM {
calculate_memory_size(return_data_start_offset, return_data_size)?;
let new_memory_size = new_memory_size_for_args.max(new_memory_size_for_return_data);

let (is_delegation, eip7702_gas_consumed, _, bytecode) =
self.eip7702_get_code(code_address)?;
let (is_delegation, eip7702_gas_consumed, _, bytecode) = eip7702_get_code(
&mut self.cache,
&mut self.db,
&mut self.accrued_substate,
code_address,
)?;

let gas_left = current_call_frame
.gas_limit
Expand Down
56 changes: 55 additions & 1 deletion crates/vm/levm/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use crate::{
execute_precompile, is_precompile, SIZE_PRECOMPILES_CANCUN, SIZE_PRECOMPILES_PRAGUE,
SIZE_PRECOMPILES_PRE_CANCUN,
},
vm::{AccessList, AuthorizationList, AuthorizationTuple},
vm::{AccessList, AuthorizationList, AuthorizationTuple, Substate},
AccountInfo, TransientStorage,
};
use bytes::Bytes;
Expand Down Expand Up @@ -548,3 +548,57 @@ pub fn eip7702_recover_address(
.map_err(|_| VMError::Internal(InternalError::ConversionError))?;
Ok(Some(Address::from_slice(&authority_address_bytes)))
}

/// Used for the opcodes
/// The following reading instructions are impacted:
/// EXTCODESIZE, EXTCODECOPY, EXTCODEHASH
/// and the following executing instructions are impacted:
/// CALL, CALLCODE, STATICCALL, DELEGATECALL
/// In case a delegation designator points to another designator,
/// creating a potential chain or loop of designators, clients must
/// retrieve only the first code and then stop following the
/// designator chain.
///
/// For example,
/// EXTCODESIZE would return 2 (the size of 0xef01) instead of 23
/// which would represent the delegation designation, EXTCODEHASH
/// would return
/// 0xeadcdba66a79ab5dce91622d1d75c8cff5cff0b96944c3bf1072cd08ce018329
/// (keccak256(0xef01)), and CALL would load the code from address and
/// execute it in the context of authority.
///
/// The idea of this function comes from ethereum/execution-specs:
/// https://github.com/ethereum/execution-specs/blob/951fc43a709b493f27418a8e57d2d6f3608cef84/src/ethereum/prague/vm/eoa_delegation.py#L115
pub fn eip7702_get_code(
cache: &mut CacheDB,
db: &Arc<dyn Database>,
accrued_substate: &mut Substate,
address: Address,
) -> Result<(bool, u64, Address, Bytes), VMError> {
// Address is the delgated address
let account = get_account(cache, db, address);
let bytecode = account.info.bytecode.clone();

// If the Address doesn't have a delegation code
// return false meaning that is not a delegation
// return the same address given
// return the bytecode of the given address
if !has_delegation(&account.info)? {
return Ok((false, 0, address, bytecode));
}

// Here the address has a delegation code
// The delegation code has the authorized address
let auth_address = get_authorized_address(&account.info)?;

let access_cost = if accrued_substate.touched_accounts.contains(&auth_address) {
WARM_ADDRESS_ACCESS_COST
} else {
accrued_substate.touched_accounts.insert(auth_address);
COLD_ADDRESS_ACCESS_COST
};

let authorized_bytecode = get_account(cache, db, auth_address).info.bytecode;

Ok((true, access_cost, auth_address, authorized_bytecode))
}
54 changes: 0 additions & 54 deletions crates/vm/levm/src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1220,58 +1220,4 @@ impl VM {
get_valid_jump_destinations(&initial_call_frame.bytecode).unwrap_or_default();
Ok(refunded_gas)
}

/// Used for the opcodes
/// The following reading instructions are impacted:
/// EXTCODESIZE, EXTCODECOPY, EXTCODEHASH
/// and the following executing instructions are impacted:
/// CALL, CALLCODE, STATICCALL, DELEGATECALL
/// In case a delegation designator points to another designator,
/// creating a potential chain or loop of designators,
/// clients must retrieve only the first code and then stop following the designator chain.
///
/// For example,
/// EXTCODESIZE would return 2 (the size of 0xef01) instead of 23 which would represent the delegation designation,
/// EXTCODEHASH would return 0xeadcdba66a79ab5dce91622d1d75c8cff5cff0b96944c3bf1072cd08ce018329 (keccak256(0xef01)), and
/// CALL would load the code from address and execute it in the context of authority.
///
/// The idea of this function comes from ethereum/execution-specs:
/// https://github.com/ethereum/execution-specs/blob/951fc43a709b493f27418a8e57d2d6f3608cef84/src/ethereum/prague/vm/eoa_delegation.py#L115
pub fn eip7702_get_code(
&mut self,
address: Address,
) -> Result<(bool, u64, Address, Bytes), VMError> {
// Address is the delgated address
let account = get_account(&mut self.cache, &self.db, address);
let bytecode = account.info.bytecode.clone();

// If the Address doesn't have a delegation code
// return false meaning that is not a delegation
// return the same address given
// return the bytecode of the given address
if !has_delegation(&account.info)? {
return Ok((false, 0, address, bytecode));
}

// Here the address has a delegation code
// The delegation code has the authorized address
let auth_address = get_authorized_address(&account.info)?;

let access_cost = if self
.accrued_substate
.touched_accounts
.contains(&auth_address)
{
WARM_ADDRESS_ACCESS_COST
} else {
self.accrued_substate.touched_accounts.insert(auth_address);
COLD_ADDRESS_ACCESS_COST
};

let authorized_bytecode = get_account(&mut self.cache, &self.db, auth_address)
.info
.bytecode;

Ok((true, access_cost, auth_address, authorized_bytecode))
}
}

0 comments on commit 73c8301

Please sign in to comment.