From 85e2864a7f43731bb0aec96f09f5202278284fd2 Mon Sep 17 00:00:00 2001 From: Pia <76558220+rkdud007@users.noreply.github.com> Date: Tue, 12 Sep 2023 01:31:30 +0900 Subject: [PATCH] add msize opcode (#286) --- .../src/instructions/memory_operations.cairo | 3 +- crates/evm/src/memory.cairo | 7 +++ .../test_memory_operations.cairo | 49 +++++++++++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) diff --git a/crates/evm/src/instructions/memory_operations.cairo b/crates/evm/src/instructions/memory_operations.cairo index ab8df370a..9074572ab 100644 --- a/crates/evm/src/instructions/memory_operations.cairo +++ b/crates/evm/src/instructions/memory_operations.cairo @@ -41,7 +41,8 @@ impl MemoryOperation of MemoryOperationTrait { /// Get the value of memory size. /// # Specification: https://www.evm.codes/#59?fork=shanghai fn exec_msize(ref self: ExecutionContext) -> Result<(), EVMError> { - Result::Ok(()) + let msize: u256 = self.memory.size().into(); + self.stack.push(msize) } /// 0x56 - JUMP operation diff --git a/crates/evm/src/memory.cairo b/crates/evm/src/memory.cairo index 73118a455..5552afa10 100644 --- a/crates/evm/src/memory.cairo +++ b/crates/evm/src/memory.cairo @@ -15,6 +15,7 @@ struct Memory { trait MemoryTrait { fn new() -> Memory; + fn size(ref self: Memory) -> usize; fn store(ref self: Memory, element: u256, offset: usize); fn store_n(ref self: Memory, elements: Span, offset: usize); fn ensure_length(ref self: Memory, length: usize) -> usize; @@ -31,6 +32,12 @@ impl MemoryImpl of MemoryTrait { Memory { items: Default::default(), bytes_len: 0, } } + /// Return size of the memory. + #[inline(always)] + fn size(ref self: Memory) -> usize { + self.bytes_len + } + /// Stores a 32-bytes element into the memory. /// /// If the offset is aligned with the 16-bytes words in memory, the element is stored directly. diff --git a/crates/evm/src/tests/test_instructions/test_memory_operations.cairo b/crates/evm/src/tests/test_instructions/test_memory_operations.cairo index 0c79ecc9c..6594fc4bc 100644 --- a/crates/evm/src/tests/test_instructions/test_memory_operations.cairo +++ b/crates/evm/src/tests/test_instructions/test_memory_operations.cairo @@ -12,6 +12,7 @@ use evm::errors::{EVMError, STACK_UNDERFLOW}; use evm::context::{ ExecutionContext, ExecutionContextTrait, BoxDynamicExecutionContextDestruct, CallContextTrait, }; +use evm::helpers::U256IntoResultU32; use integer::BoundedInt; @@ -251,3 +252,51 @@ fn test_exec_mstore8_should_store_last_uint8_offset_63() { let (stored, _) = ctx.memory.load(32); assert(stored == 0xEF, 'mstore8 failed'); } + + +#[test] +#[available_gas(20000000)] +fn test_msize_initial() { + // Given + let mut ctx = setup_execution_context(); + + // When + let result = ctx.exec_msize(); + + // Then + assert(result.is_ok(), 'should have succeeded'); + assert(ctx.stack.len() == 1, 'stack should have one element'); + assert(ctx.stack.pop().unwrap() == 0, 'initial memory size should be 0'); +} + +#[test] +#[available_gas(20000000)] +fn test_exec_msize_store_max_offset_0() { + // Given + let mut ctx = setup_execution_context(); + ctx.memory.store(BoundedInt::::max(), 0x00); + + // When + let result = ctx.exec_msize(); + + // Then + assert(result.is_ok(), 'should have succeeded'); + assert(ctx.stack.len() == 1, 'stack should have one element'); + assert(ctx.stack.pop().unwrap() == 32, 'should 32 bytes after MSTORE'); +} + +#[test] +#[available_gas(20000000)] +fn test_exec_msize_store_max_offset_1() { + // Given + let mut ctx = setup_execution_context(); + ctx.memory.store(BoundedInt::::max(), 0x01); + + // When + let result = ctx.exec_msize(); + + // Then + assert(result.is_ok(), 'should have succeeded'); + assert(ctx.stack.len() == 1, 'stack should have one element'); + assert(ctx.stack.pop().unwrap() == 64, 'should 64 bytes after MSTORE'); +}