diff --git a/crates/evm/src/context.cairo b/crates/evm/src/context.cairo index b9b442c29..830f0ef80 100644 --- a/crates/evm/src/context.cairo +++ b/crates/evm/src/context.cairo @@ -116,6 +116,12 @@ impl DefaultBoxCallContext of Default> { } } +impl DefaultOptionSpanU8 of Default>> { + fn default() -> Option> { + Option::None + } +} + // ************************************************************************* // ExecutionContext @@ -136,7 +142,7 @@ struct ExecutionContext { create_addresses: Array, return_data: Array, parent_context: Nullable, - child_context: Nullable, + child_context_return_data: Option>, } impl DefaultBoxExecutionContext of Default> { @@ -159,7 +165,7 @@ impl ExecutionContextImpl of ExecutionContextTrait { starknet_address: ContractAddress, call_context: CallContext, parent_context: Nullable, - child_context: Nullable, + child_context_return_data: Option>, return_data: Array, ) -> ExecutionContext { ExecutionContext { @@ -184,7 +190,7 @@ impl ExecutionContextImpl of ExecutionContextTrait { create_addresses: Default::default(), return_data, parent_context, - child_context, + child_context_return_data, } } @@ -314,4 +320,9 @@ impl ExecutionContextImpl of ExecutionContextTrait { fn pc(self: @ExecutionContext) -> u32 { *self.program_counter } + + #[inline(always)] + fn child_context_return_data(self: @ExecutionContext) -> Option> { + *self.child_context_return_data + } } diff --git a/crates/evm/src/machine.cairo b/crates/evm/src/machine.cairo index b1a1014c7..3bffb710e 100644 --- a/crates/evm/src/machine.cairo +++ b/crates/evm/src/machine.cairo @@ -252,4 +252,14 @@ impl MachineCurrentContextImpl of MachineCurrentContextTrait { current_execution_ctx.return_data = value; self.current_context = BoxTrait::new(current_execution_ctx); } + + /// Getter for the return data of a child context, accessed from its parent context + /// Enabler for RETURNDATASIZE and RETURNDATACOPY opcodes + #[inline(always)] + fn child_context_return_data(ref self: Machine) -> Option> { + let mut current_execution_ctx = self.current_context.unbox(); + let child_context_return_data = current_execution_ctx.child_context_return_data(); + self.current_context = BoxTrait::new(current_execution_ctx); + child_context_return_data + } } diff --git a/crates/evm/src/tests/test_execution_context.cairo b/crates/evm/src/tests/test_execution_context.cairo index caa4faf89..9ae74032a 100644 --- a/crates/evm/src/tests/test_execution_context.cairo +++ b/crates/evm/src/tests/test_execution_context.cairo @@ -1,6 +1,8 @@ use core::nullable::{NullableTrait, null}; use debug::PrintTrait; -use evm::context::{CallContext, CallContextTrait, ExecutionContext, ExecutionContextTrait}; +use evm::context::{ + CallContext, CallContextTrait, ExecutionContext, ExecutionContextTrait, DefaultOptionSpanU8 +}; use evm::memory::{Memory, MemoryTrait}; use evm::model::Event; use evm::stack::{Stack, StackTrait}; @@ -64,7 +66,6 @@ fn test_execution_context_new() { let read_only: bool = false; let parent_context: Nullable = null(); - let child_context: Nullable = null(); // When let mut execution_context = ExecutionContextTrait::new( @@ -73,7 +74,7 @@ fn test_execution_context_new() { starknet_address, call_context, parent_context, - child_context, + Default::default(), return_data ); @@ -143,12 +144,27 @@ fn test_execution_context_read_code() { #[available_gas(300000)] #[ignore] fn test_is_root() { - // TODO: finish this test once calling_contexts are implemented // Given let mut execution_context = setup_execution_context(); // When let is_root = execution_context.is_root(); -// Then -// assert(is_root == true, 'should not be a leaf'); + + // Then + assert(is_root, 'should not be a leaf'); +} + + +#[test] +#[available_gas(300000)] +#[ignore] +fn test_child_context_return_data() { + // Given + let mut execution_context = setup_execution_context(); + + // When + let child_return_data = execution_context.child_context_return_data().unwrap(); + + // Then + assert(child_return_data == array![1, 2, 3].span(), 'should not be a leaf'); } diff --git a/crates/evm/src/tests/test_machine.cairo b/crates/evm/src/tests/test_machine.cairo index 50841f94b..12479a5ab 100644 --- a/crates/evm/src/tests/test_machine.cairo +++ b/crates/evm/src/tests/test_machine.cairo @@ -161,3 +161,13 @@ fn test_return_data() { let return_data = machine.return_data(); assert(return_data.len() == 0, 'wrong length'); } + + +#[test] +#[available_gas(20000000)] +fn test_child_context_return_data() { + let mut machine: Machine = setup_machine(); + + let return_data = machine.child_context_return_data().unwrap(); + assert(return_data == array![1, 2, 3].span(), 'wrong child return data'); +} diff --git a/crates/evm/src/tests/test_utils.cairo b/crates/evm/src/tests/test_utils.cairo index c79b432c3..63bcb50ae 100644 --- a/crates/evm/src/tests/test_utils.cairo +++ b/crates/evm/src/tests/test_utils.cairo @@ -1,4 +1,6 @@ -use evm::context::{CallContext, CallContextTrait, ExecutionContext, ExecutionContextTrait,}; +use evm::context::{ + CallContext, CallContextTrait, ExecutionContext, ExecutionContextTrait, DefaultOptionSpanU8 +}; use evm::machine::Machine; use starknet::{contract_address_try_from_felt252, ContractAddress, EthAddress}; @@ -37,6 +39,7 @@ fn setup_execution_context() -> ExecutionContext { let starknet_address: ContractAddress = starknet_address(); let evm_address: EthAddress = evm_address(); let return_data = Default::default(); + let child_context_return_data = Option::Some(array![1, 2, 3].span()); ExecutionContextTrait::new( context_id, @@ -44,7 +47,7 @@ fn setup_execution_context() -> ExecutionContext { starknet_address, call_context, Default::default(), - Default::default(), + child_context_return_data, return_data, ) }