Skip to content

Commit

Permalink
feat(EOF): disallow ExtDelegateCall to legacy bytecode (bluealloy#1572)
Browse files Browse the repository at this point in the history
* Wip call ext

* feat(EOF): disallow ExtDelegateCall to legacy bytecode
  • Loading branch information
rakita authored Jun 27, 2024
1 parent 27b67a0 commit d3ff9cf
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 5 deletions.
8 changes: 8 additions & 0 deletions crates/interpreter/src/instruction_result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ pub enum InstructionResult {
CreateInitCodeStartingEF00,
/// Invalid EOF initcode,
InvalidEOFInitCode,
/// ExtDelegateCall calling a non EOF contract.
InvalidExtDelegateCallTarget,

// Actions
CallOrCreate = 0x20,
Expand Down Expand Up @@ -132,6 +134,7 @@ macro_rules! return_revert {
| InstructionResult::OutOfFunds
| InstructionResult::InvalidEOFInitCode
| InstructionResult::CreateInitCodeStartingEF00
| InstructionResult::InvalidExtDelegateCallTarget
};
}

Expand Down Expand Up @@ -200,6 +203,8 @@ pub enum InternalResult {
CreateInitCodeStartingEF00,
/// Check for target address validity is only done inside subcall.
InvalidEXTCALLTarget,
/// Internal to ExtDelegateCall
InvalidExtDelegateCallTarget,
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
Expand Down Expand Up @@ -311,6 +316,9 @@ impl From<InstructionResult> for SuccessOrHalt {
InstructionResult::InvalidEXTCALLTarget => {
Self::Internal(InternalResult::InvalidEXTCALLTarget)
}
InstructionResult::InvalidExtDelegateCallTarget => {
Self::Internal(InternalResult::InvalidExtDelegateCallTarget)
}
}
}
}
Expand Down
7 changes: 3 additions & 4 deletions crates/interpreter/src/instructions/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ pub fn extcall<H: Host + ?Sized, SPEC: Spec>(interpreter: &mut Interpreter, host
caller: interpreter.contract.target_address,
bytecode_address: target_address,
value: CallValue::Transfer(value),
scheme: CallScheme::Call,
scheme: CallScheme::ExtCall,
is_static: interpreter.is_static,
is_eof: true,
return_memory_offset: 0..0,
Expand Down Expand Up @@ -277,8 +277,7 @@ pub fn extdelegatecall<H: Host + ?Sized, SPEC: Spec>(interpreter: &mut Interpret
caller: interpreter.contract.caller,
bytecode_address: target_address,
value: CallValue::Apparent(interpreter.contract.call_value),
// TODO(EOF) should be EofDelegateCall?
scheme: CallScheme::DelegateCall,
scheme: CallScheme::ExtDelegateCall,
is_static: interpreter.is_static,
is_eof: true,
return_memory_offset: 0..0,
Expand Down Expand Up @@ -313,7 +312,7 @@ pub fn extstaticcall<H: Host + ?Sized>(interpreter: &mut Interpreter, host: &mut
caller: interpreter.contract.target_address,
bytecode_address: target_address,
value: CallValue::Transfer(U256::ZERO),
scheme: CallScheme::Call,
scheme: CallScheme::ExtStaticCall,
is_static: true,
is_eof: true,
return_memory_offset: 0..0,
Expand Down
21 changes: 21 additions & 0 deletions crates/interpreter/src/interpreter_action/call_inputs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,27 @@ pub enum CallScheme {
DelegateCall,
/// `STATICCALL`
StaticCall,
/// `EXTCALL`
ExtCall,
/// `EXTSTATICCALL`
ExtStaticCall,
/// `EXTDELEGATECALL`
ExtDelegateCall,
}

impl CallScheme {
/// Returns true if it is EOF EXT*CALL.
pub fn is_ext(&self) -> bool {
matches!(
self,
Self::ExtCall | Self::ExtStaticCall | Self::ExtDelegateCall
)
}

/// Returns true if it is ExtDelegateCall.
pub fn is_ext_delegate_call(&self) -> bool {
matches!(self, Self::ExtDelegateCall)
}
}

/// Call value.
Expand Down
10 changes: 9 additions & 1 deletion crates/revm/src/context/evm_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::{
interpreter::{
return_ok, CallInputs, Contract, Gas, InstructionResult, Interpreter, InterpreterResult,
},
primitives::{Address, Bytes, EVMError, Env, U256},
primitives::{Address, Bytes, EVMError, Env, EOF_MAGIC_BYTES, U256},
ContextPrecompiles, FrameOrResult, CALL_STACK_LIMIT,
};
use core::{
Expand Down Expand Up @@ -170,9 +170,17 @@ impl<DB: Database> EvmContext<DB> {
.inner
.journaled_state
.load_code(inputs.bytecode_address, &mut self.inner.db)?;

let code_hash = account.info.code_hash();
let bytecode = account.info.code.clone().unwrap_or_default();

// ExtDelegateCall is not allowed to call non-EOF contracts.
if inputs.scheme.is_ext_delegate_call()
&& bytecode.bytes_slice().get(..2) != Some(&EOF_MAGIC_BYTES)
{
return return_result(InstructionResult::InvalidExtDelegateCallTarget);
}

// Create subroutine checkpoint
let checkpoint = self.journaled_state.checkpoint();

Expand Down

0 comments on commit d3ff9cf

Please sign in to comment.