diff --git a/crates/evm/src/instructions/logging_operations.cairo b/crates/evm/src/instructions/logging_operations.cairo index 7baea5354..e19360c38 100644 --- a/crates/evm/src/instructions/logging_operations.cairo +++ b/crates/evm/src/instructions/logging_operations.cairo @@ -98,7 +98,7 @@ mod tests { use evm::memory::MemoryTrait; use evm::stack::StackTrait; use evm::state::StateTrait; - use evm::test_utils::{VMBuilderTrait}; + use evm::test_utils::{VMBuilderTrait, MemoryTestUtilsTrait}; use utils::helpers::u256_to_bytes_array; #[test] @@ -106,7 +106,7 @@ mod tests { // Given let mut vm = VMBuilderTrait::new_with_presets().build(); - vm.memory.store(Bounded::::MAX, 0); + vm.memory.store_with_expansion(Bounded::::MAX, 0); vm.stack.push(0x1F).expect('push failed'); vm.stack.push(0x00).expect('push failed'); @@ -134,7 +134,7 @@ mod tests { // Given let mut vm = VMBuilderTrait::new_with_presets().build(); - vm.memory.store(Bounded::::MAX, 0); + vm.memory.store_with_expansion(Bounded::::MAX, 0); vm.stack.push(0x0123456789ABCDEF).expect('push failed'); vm.stack.push(0x20).expect('push failed'); @@ -164,7 +164,7 @@ mod tests { // Given let mut vm = VMBuilderTrait::new_with_presets().build(); - vm.memory.store(Bounded::::MAX, 0); + vm.memory.store_with_expansion(Bounded::::MAX, 0); vm.stack.push(Bounded::::MAX).expect('push failed'); vm.stack.push(0x0123456789ABCDEF).expect('push failed'); @@ -196,8 +196,8 @@ mod tests { // Given let mut vm = VMBuilderTrait::new_with_presets().build(); - vm.memory.store(Bounded::::MAX, 0); - vm.memory.store(0x0123456789ABCDEF000000000000000000000000000000000000000000000000, 0x20); + vm.memory.store_with_expansion(Bounded::::MAX, 0); + vm.memory.store_with_expansion(0x0123456789ABCDEF000000000000000000000000000000000000000000000000, 0x20); vm.stack.push(0x00).expect('push failed'); vm.stack.push(Bounded::::MAX).expect('push failed'); @@ -233,8 +233,8 @@ mod tests { // Given let mut vm = VMBuilderTrait::new_with_presets().build(); - vm.memory.store(Bounded::::MAX, 0); - vm.memory.store(0x0123456789ABCDEF000000000000000000000000000000000000000000000000, 0x20); + vm.memory.store_with_expansion(Bounded::::MAX, 0); + vm.memory.store_with_expansion(0x0123456789ABCDEF000000000000000000000000000000000000000000000000, 0x20); vm.stack.push(Bounded::::MAX).expect('push failed'); vm.stack.push(0x00).expect('push failed'); @@ -270,7 +270,7 @@ mod tests { // Given let mut vm = VMBuilderTrait::new().with_read_only().build(); - vm.memory.store(Bounded::::MAX, 0); + vm.memory.store_with_expansion(Bounded::::MAX, 0); vm.stack.push(0x0123456789ABCDEF).expect('push failed'); vm.stack.push(0x20).expect('push failed'); @@ -291,7 +291,7 @@ mod tests { // Given let mut vm = VMBuilderTrait::new_with_presets().build(); - vm.memory.store(Bounded::::MAX, 0); + vm.memory.store_with_expansion(Bounded::::MAX, 0); vm.stack.push(0x0123456789ABCDEF).expect('push failed'); vm.stack.push(0x00).expect('push failed'); @@ -319,7 +319,7 @@ mod tests { // Given let mut vm = VMBuilderTrait::new_with_presets().build(); - vm.memory.store(Bounded::::MAX, 0); + vm.memory.store_with_expansion(Bounded::::MAX, 0); vm.stack.push(0x0123456789ABCDEF).expect('push failed'); vm.stack.push(Bounded::::MAX).expect('push failed'); @@ -341,7 +341,7 @@ mod tests { // Given let mut vm = VMBuilderTrait::new_with_presets().build(); - vm.memory.store(Bounded::::MAX, 0); + vm.memory.store_with_expansion(Bounded::::MAX, 0); vm.stack.push(0x0123456789ABCDEF).expect('push failed'); vm.stack.push(0x20).expect('push failed'); @@ -363,8 +363,8 @@ mod tests { // Given let mut vm = VMBuilderTrait::new_with_presets().build(); - vm.memory.store(Bounded::::MAX, 0); - vm.memory.store(0x0123456789ABCDEF000000000000000000000000000000000000000000000000, 0x20); + vm.memory.store_with_expansion(Bounded::::MAX, 0); + vm.memory.store_with_expansion(0x0123456789ABCDEF000000000000000000000000000000000000000000000000, 0x20); vm.stack.push(Bounded::::MAX).expect('push failed'); vm.stack.push(0x00).expect('push failed'); diff --git a/crates/evm/src/instructions/memory_operations.cairo b/crates/evm/src/instructions/memory_operations.cairo index 1190cae38..0212d578f 100644 --- a/crates/evm/src/instructions/memory_operations.cairo +++ b/crates/evm/src/instructions/memory_operations.cairo @@ -326,8 +326,8 @@ mod tests { use evm::stack::StackTrait; use evm::state::{StateTrait, compute_storage_address}; use evm::test_utils::{ - evm_address, VMBuilderTrait, setup_test_storages, register_account, uninitialized_account, - native_token + evm_address, VMBuilderTrait, MemoryTestUtilsTrait, setup_test_storages, register_account, + uninitialized_account, native_token }; use snforge_std::{test_address, start_mock_call, store}; use snforge_utils::snforge_utils::store_evm; @@ -381,7 +381,7 @@ mod tests { fn assert_mload(value: u256, offset: u256, expected_value: u256, expected_memory_size: u32) { // Given let mut vm = VMBuilderTrait::new_with_presets().build(); - vm.memory.store(value, 0); + vm.memory.store_with_expansion(value, 0); vm.stack.push(offset).expect('push failed'); @@ -569,10 +569,10 @@ mod tests { } #[test] - fn test_exec_msize_store_max_offset_0() { + fn test_exec_msize_should_return_size_of_memory() { // Given let mut vm = VMBuilderTrait::new_with_presets().build(); - vm.memory.store(Bounded::::MAX, 0x00); + vm.memory.store_with_expansion(Bounded::::MAX, 0x00); // When let result = vm.exec_msize(); @@ -580,22 +580,7 @@ mod tests { // Then assert(result.is_ok(), 'should have succeeded'); assert(vm.stack.len() == 1, 'stack should have one element'); - assert(vm.stack.pop().unwrap() == 32, 'should 32 bytes after MSTORE'); - } - - #[test] - fn test_exec_msize_store_max_offset_1() { - // Given - let mut vm = VMBuilderTrait::new_with_presets().build(); - vm.memory.store(Bounded::::MAX, 0x01); - - // When - let result = vm.exec_msize(); - - // Then - assert(result.is_ok(), 'should have succeeded'); - assert(vm.stack.len() == 1, 'stack should have one element'); - assert(vm.stack.pop().unwrap() == 64, 'should 64 bytes after MSTORE'); + assert(vm.stack.pop().unwrap() == 32, 'should 32 bytes after MSIZE'); } #[test] @@ -1049,7 +1034,7 @@ mod tests { let mut i = 0; for element in values .span() { - vm.memory.store((*element).into(), source_offset + 0x20 * i); + vm.memory.store_with_expansion((*element).into(), source_offset + 0x20 * i); i += 1; }; vm.stack.push(dest_offset.into()).expect('push failed'); @@ -1058,7 +1043,9 @@ mod tests { // When let expected_gas = gas::VERYLOW - + gas::memory_expansion(vm.memory.size(), [(max(dest_offset, source_offset), size)].span()) + + gas::memory_expansion( + vm.memory.size(), [(max(dest_offset, source_offset), size)].span() + ) .expansion_cost; let gas_before = vm.gas_left(); let result = vm.exec_mcopy(); diff --git a/crates/evm/src/instructions/sha3.cairo b/crates/evm/src/instructions/sha3.cairo index ea827ca01..73ba94c00 100644 --- a/crates/evm/src/instructions/sha3.cairo +++ b/crates/evm/src/instructions/sha3.cairo @@ -159,7 +159,7 @@ mod tests { use evm::instructions::sha3::internal; use evm::memory::{InternalMemoryTrait, MemoryTrait}; use evm::stack::StackTrait; - use evm::test_utils::VMBuilderTrait; + use evm::test_utils::{VMBuilderTrait, MemoryTestUtilsTrait}; #[test] fn test_exec_sha3_size_0_offset_0() { @@ -169,7 +169,7 @@ mod tests { vm.stack.push(0x00).expect('push failed'); vm.stack.push(0x00).expect('push failed'); - vm.memory.store(0xFFFFFFFF00000000000000000000000000000000000000000000000000000000, 0); + vm.memory.store_with_expansion(0xFFFFFFFF00000000000000000000000000000000000000000000000000000000, 0); // When vm.exec_sha3().expect('exec_sha3 failed'); @@ -186,14 +186,14 @@ mod tests { #[test] - fn test_exec_sha3_size_5_offset_4() { + fn test_exec_sha3_should_not_expand_memory() { // Given let mut vm = VMBuilderTrait::new_with_presets().build(); vm.stack.push(0x05).expect('push failed'); vm.stack.push(0x04).expect('push failed'); - vm.memory.store(0xFFFFFFFF00000000000000000000000000000000000000000000000000000000, 0); + vm.memory.store_with_expansion(0xFFFFFFFF00000000000000000000000000000000000000000000000000000000, 0); // When vm.exec_sha3().expect('exec_sha3 failed'); @@ -204,29 +204,26 @@ mod tests { result == 0xc41589e7559804ea4a2080dad19d876a024ccb05117835447d72ce08c1d020ec, 'wrong result' ); - assert(vm.memory.size() == 64, 'wrong memory size'); + assert_eq!(vm.memory.size(), 32, 'wrong memory size'); } #[test] - fn test_exec_sha3_size_10_offset_10() { + fn test_exec_sha3_should_expand_memory() { // Given let mut vm = VMBuilderTrait::new_with_presets().build(); - vm.stack.push(10).expect('push failed'); + vm.stack.push(24).expect('push failed'); vm.stack.push(10).expect('push failed'); - vm.memory.store(0xFFFFFFFF00000000000000000000000000000000000000000000000000000000, 0); + vm.memory.store_with_expansion(0xFFFFFFFF00000000000000000000000000000000000000000000000000000000, 0); // When vm.exec_sha3().expect('exec_sha3 failed'); // Then let result = vm.stack.peek().unwrap(); - assert( - result == 0x6bd2dd6bd408cbee33429358bf24fdc64612fbf8b1b4db604518f40ffd34b607, - 'wrong result' - ); - assert(vm.memory.size() == 64, 'wrong memory size'); + assert_eq!(result, 0x827b659bbda2a0bdecce2c91b8b68462545758f3eba2dbefef18e0daf84f5ccd); + assert_eq!(vm.memory.size(), 64); } #[test] @@ -237,7 +234,7 @@ mod tests { vm.stack.push(0xFFFFF).expect('push failed'); vm.stack.push(1000).expect('push failed'); - vm.memory.store(0xFFFFFFFF00000000000000000000000000000000000000000000000000000000, 0); + vm.memory.store_with_expansion(0xFFFFFFFF00000000000000000000000000000000000000000000000000000000, 0); // When vm.exec_sha3().expect('exec_sha3 failed'); @@ -259,7 +256,7 @@ mod tests { vm.stack.push(1000000).expect('push failed'); vm.stack.push(2).expect('push failed'); - vm.memory.store(0xFFFFFFFF00000000000000000000000000000000000000000000000000000000, 0); + vm.memory.store_with_expansion(0xFFFFFFFF00000000000000000000000000000000000000000000000000000000, 0); // When vm.exec_sha3().expect('exec_sha3 failed'); @@ -281,8 +278,8 @@ mod tests { vm.stack.push(1000000).expect('push failed'); vm.stack.push(2).expect('push failed'); - vm.memory.store(0xFFFFFFFF00000000000000000000000000000000000000000000000000000000, 0); - vm.memory.store(0xFFFFFFFF00000000000000000000000000000000000000000000000000000000, 0); + vm.memory.store_with_expansion(0xFFFFFFFF00000000000000000000000000000000000000000000000000000000, 0); + vm.memory.store_with_expansion(0xFFFFFFFF00000000000000000000000000000000000000000000000000000000, 0); // When vm.exec_sha3().expect('exec_sha3 failed'); @@ -304,7 +301,7 @@ mod tests { vm.stack.push(1).expect('push failed'); vm.stack.push(2048).expect('push failed'); - vm.memory.store(0xFFFFFFFF00000000000000000000000000000000000000000000000000000000, 0); + vm.memory.store_with_expansion(0xFFFFFFFF00000000000000000000000000000000000000000000000000000000, 0); // When vm.exec_sha3().expect('exec_sha3 failed'); @@ -326,7 +323,7 @@ mod tests { vm.stack.push(0).expect('push failed'); vm.stack.push(1024).expect('push failed'); - vm.memory.store(0xFFFFFFFF00000000000000000000000000000000000000000000000000000000, 0); + vm.memory.store_with_expansion(0xFFFFFFFF00000000000000000000000000000000000000000000000000000000, 0); // When vm.exec_sha3().expect('exec_sha3 failed'); @@ -348,7 +345,7 @@ mod tests { vm.stack.push(32).expect('push failed'); vm.stack.push(2016).expect('push failed'); - vm.memory.store(0xFFFFFFFF00000000000000000000000000000000000000000000000000000000, 0); + vm.memory.store_with_expansion(0xFFFFFFFF00000000000000000000000000000000000000000000000000000000, 0); // When vm.exec_sha3().expect('exec_sha3 failed'); @@ -370,7 +367,7 @@ mod tests { vm.stack.push(32).expect('push failed'); vm.stack.push(0).expect('push failed'); - vm.memory.store(0xFAFFFFFF000000E500000077000000DEAD0000000004200000FADE0000450000, 0); + vm.memory.store_with_expansion(0xFAFFFFFF000000E500000077000000DEAD0000000004200000FADE0000450000, 0); // When vm.exec_sha3().expect('exec_sha3 failed'); @@ -392,7 +389,7 @@ mod tests { vm.stack.push(31).expect('push failed'); vm.stack.push(0).expect('push failed'); - vm.memory.store(0xFAFFFFFF000000E500000077000000DEAD0000000004200000FADE0000450000, 0); + vm.memory.store_with_expansion(0xFAFFFFFF000000E500000077000000DEAD0000000004200000FADE0000450000, 0); // When vm.exec_sha3().expect('exec_sha3 failed'); @@ -414,7 +411,7 @@ mod tests { vm.stack.push(33).expect('push failed'); vm.stack.push(0).expect('push failed'); - vm.memory.store(0xFAFFFFFF000000E500000077000000DEAD0000000004200000FADE0000450000, 0); + vm.memory.store_with_expansion(0xFAFFFFFF000000E500000077000000DEAD0000000004200000FADE0000450000, 0); // When vm.exec_sha3().expect('exec_sha3 failed'); @@ -440,7 +437,7 @@ mod tests { while mem_dst <= 0x0C80 { vm .memory - .store(0xFAFAFAFA00000000000000000000000000000000000000000000000000000000, mem_dst); + .store_with_expansion(0xFAFAFAFA00000000000000000000000000000000000000000000000000000000, mem_dst); mem_dst += 0x20; }; @@ -462,7 +459,7 @@ mod tests { let mut vm = VMBuilderTrait::new_with_presets().build(); let mut to_hash: Array = Default::default(); - vm.memory.store(0xFAFFFFFF000000E500000077000000DEAD0000000004200000FADE0000450000, 0); + vm.memory.store_with_expansion(0xFAFFFFFF000000E500000077000000DEAD0000000004200000FADE0000450000, 0); let mut size = 32; let mut offset = 0; @@ -486,7 +483,7 @@ mod tests { let mut vm = VMBuilderTrait::new_with_presets().build(); let mut to_hash: Array = Default::default(); - vm.memory.store(0xFAFFFFFF000000E500000077000000DEAD0000000004200000FADE0000450000, 0); + vm.memory.store_with_expansion(0xFAFFFFFF000000E500000077000000DEAD0000000004200000FADE0000450000, 0); let mut size = 33; let mut offset = 0; diff --git a/crates/evm/src/instructions/system_operations.cairo b/crates/evm/src/instructions/system_operations.cairo index f8a7eb1d3..fb1cf4bed 100644 --- a/crates/evm/src/instructions/system_operations.cairo +++ b/crates/evm/src/instructions/system_operations.cairo @@ -117,20 +117,9 @@ impl SystemOperations of SystemOperationsTrait { let ret_offset = self.stack.pop_usize()?; let ret_size = self.stack.pop_usize()?; - let args_max_offset = args_offset + args_size; - let ret_max_offset = ret_offset + ret_size; - let to = self.message().target.evm; - let max_memory_size = if args_max_offset > ret_max_offset { - args_max_offset - } else { - ret_max_offset - }; - // GAS - //TODO(optimization): if we know how much the memory is going to be expanded, - // we can return the new size and save a computation later. let memory_expansion = gas::memory_expansion( self.memory.size(), [(args_offset, args_size), (ret_offset, ret_size)].span() ); @@ -213,8 +202,6 @@ impl SystemOperations of SystemOperationsTrait { let ret_size = self.stack.pop_usize()?; // GAS - //TODO(optimization): if we know how much the memory is going to be expanded, - // we can return the new size and save a computation later. let memory_expansion = gas::memory_expansion( self.memory.size(), [(args_offset, args_size), (ret_offset, ret_size)].span() ); @@ -268,8 +255,6 @@ impl SystemOperations of SystemOperationsTrait { let ret_size = self.stack.pop_usize()?; // GAS - //TODO(optimization): if we know how much the memory is going to be expanded, - // we can return the new size and save a computation later. let memory_expansion = gas::memory_expansion( self.memory.size(), [(args_offset, args_size), (ret_offset, ret_size)].span() ); @@ -405,8 +390,8 @@ mod tests { use evm::stack::StackTrait; use evm::state::{StateTrait, State}; use evm::test_utils::{ - VMBuilderTrait, native_token, evm_address, test_dual_address, other_evm_address, - setup_test_storages, register_account, origin, uninitialized_account + VMBuilderTrait, MemoryTestUtilsTrait, native_token, evm_address, test_dual_address, + other_evm_address, setup_test_storages, register_account, origin, uninitialized_account }; use openzeppelin::token::erc20::interface::{IERC20CamelDispatcher, IERC20CamelDispatcherTrait}; use snforge_std::{test_address, start_mock_call}; @@ -963,7 +948,7 @@ mod tests { // Load into memory the bytecode of Storage.sol let storage_initcode = storage_evm_initcode(); - vm.memory.store_n(storage_initcode, 0); + vm.memory.store_n_with_expansion(storage_initcode, 0); vm.stack.push(storage_initcode.len().into()).unwrap(); vm.stack.push(0).expect('push failed'); @@ -1029,7 +1014,7 @@ mod tests { // Load into memory the bytecode to init, which is the revert opcode let revert_initcode = [0xFD].span(); - vm.memory.store_n(revert_initcode, 0); + vm.memory.store_n_with_expansion(revert_initcode, 0); vm.stack.push(revert_initcode.len().into()).unwrap(); vm.stack.push(0).expect('push failed'); @@ -1093,7 +1078,7 @@ mod tests { // Load into memory the bytecode of Storage.sol let storage_initcode = storage_evm_initcode(); - vm.memory.store_n(storage_initcode, 0); + vm.memory.store_n_with_expansion(storage_initcode, 0); vm.stack.push(0).expect('push failed'); vm.stack.push(storage_initcode.len().into()).unwrap(); diff --git a/crates/evm/src/memory.cairo b/crates/evm/src/memory.cairo index c768881ce..230fbd877 100644 --- a/crates/evm/src/memory.cairo +++ b/crates/evm/src/memory.cairo @@ -56,10 +56,6 @@ impl MemoryImpl of MemoryTrait { /// index = Y + i * MEMORY_SEGMENT_SIZE #[inline(always)] fn store(ref self: Memory, element: u256, offset: usize) { - //TODO(optimization): new bytes len was already compute when charging the gas - let new_min_bytes_len = helpers::ceil32(offset + 32); - self.bytes_len = max(new_min_bytes_len, self.size()); - // Check alignment of offset to bytes16 chunks let (chunk_index, offset_in_chunk) = u32_safe_divmod(offset, u32_as_non_zero(16)); @@ -92,9 +88,6 @@ impl MemoryImpl of MemoryTrait { /// * `offset` - The offset within memory to store the byte at. #[inline(always)] fn store_byte(ref self: Memory, value: u8, offset: usize) { - let new_min_bytes_len = helpers::ceil32(offset + 1); - self.bytes_len = max(new_min_bytes_len, self.size()); - // Compute actual offset in Memory, given active_segment of Memory (current Execution // Context id) // And Memory Segment Size @@ -137,10 +130,6 @@ impl MemoryImpl of MemoryTrait { return; } - // Compute new bytes_len. - let new_min_bytes_len = helpers::ceil32(offset + elements.len()); - self.bytes_len = max(new_min_bytes_len, self.size()); - // Compute the offset inside the Memory, given its active segment, following the formula: // index = offset + self.active_segment * 125000 @@ -224,8 +213,6 @@ impl MemoryImpl of MemoryTrait { /// * `u256` - The loaded value. #[inline(always)] fn load(ref self: Memory, offset: usize) -> u256 { - self.ensure_length(32 + offset); - self.load_internal(offset) } @@ -233,8 +220,6 @@ impl MemoryImpl of MemoryTrait { /// inside elements. #[inline(always)] fn load_n(ref self: Memory, elements_len: usize, ref elements: Array, offset: usize) { - self.ensure_length(elements_len + offset); - self.load_n_internal(elements_len, ref elements, offset); } @@ -705,8 +690,8 @@ mod tests { memory.store(value, 0); // Then - let len = memory.size(); - assert(len == 32, 'memory should be 32bytes'); + assert_eq!(memory.items.get(0), 0); + assert_eq!(memory.items.get(1), 1); } #[test] @@ -716,11 +701,14 @@ mod tests { // When let value: u256 = 1; - memory.store(value, 1); + let offset = 1; + memory.store(value, offset); // Then - let len = memory.size(); - assert(len == 64, 'memory should be 64bytes'); + let internal_index = offset / 2; + assert_eq!(memory.items.get(internal_index.into()), 0); + assert_eq!(memory.items.get(internal_index.into() + 1), 0); + assert_eq!(memory.items.get(internal_index.into() + 2), 0x01000000000000000000000000000000); } #[test] @@ -730,20 +718,26 @@ mod tests { // When let value: u256 = 1; + let offset = 0; let bytes_array = helpers::u256_to_bytes_array(value); - memory.store_n(bytes_array.span(), 0); + memory.store_n(bytes_array.span(), offset); // Then - let len = memory.size(); - assert(len == 32, 'memory should be 32bytes'); + let internal_index = offset / 2; + assert_eq!(memory.items.get(internal_index.into()), 0); + assert_eq!(memory.items.get(internal_index.into() + 1), 1); } #[test] fn test_store_n_no_aligned_words() { let mut memory = MemoryTrait::new(); - memory.store_n([1, 2].span(), 15); - assert(memory.size() == 32, 'memory should be 32 bytes'); + let byte_offset = 15; + memory.store_n([1, 2].span(), byte_offset); + + let internal_index = byte_offset / 16; + assert_eq!(memory.items.get(internal_index.into()), 0x01); + assert_eq!(memory.items.get(internal_index.into() + 1), 0x02000000000000000000000000000000); } #[test] @@ -789,7 +783,6 @@ mod tests { memory.store_n(bytes_arr, 15); // value [1], will be stored in first word, values [2:34] will be stored in aligned words, // value [35] will be stored in final word - assert(memory.size() == 64, 'memory should be 64 bytes'); let mut stored_bytes = Default::default(); memory.load_n_internal(35, ref stored_bytes, 15); @@ -891,6 +884,7 @@ mod tests { let mut memory = MemoryTrait::new(); let value: u256 = 1; let bytes_array = helpers::u256_to_bytes_array(value); + memory.bytes_len = 32; memory.store_n(bytes_array.span(), 0); // When @@ -903,33 +897,15 @@ mod tests { } #[test] - fn test_expand__should_return_expanded_memory_and_cost() { + fn test_expand__should_return_expanded_memory_by_one_word() { // Given let mut memory = MemoryTrait::new(); - let value: u256 = 1; - let bytes_array = helpers::u256_to_bytes_array(value); - - memory.store_n(bytes_array.span(), 0); // When memory.expand(1); // Then - assert(memory.size() == 64, 'memory should be 64bytes'); - let value = memory.load_internal(0); - assert(value == 1, 'value should be 1'); - } - - #[test] - fn test_expand__should_return_expanded_memory_by_one_word_and_cost() { - // Given - let mut memory = MemoryTrait::new(); - - // When - memory.expand(1); - - // Then - assert(memory.size() == 32, 'memory should be 32bytes'); + assert_eq!(memory.size(), 32); } #[test] @@ -941,7 +917,7 @@ mod tests { memory.expand(32); // Then - assert(memory.size() == 32, 'memory should be 32bytes'); + assert_eq!(memory.size(), 32); } #[test] @@ -953,7 +929,7 @@ mod tests { memory.expand(33); // Then - assert(memory.size() == 64, 'memory should be 96bytes'); + assert_eq!(memory.size(), 64); } #[test] @@ -963,15 +939,16 @@ mod tests { let value: u256 = 1; let bytes_array = helpers::u256_to_bytes_array(value); + memory.bytes_len = 32; memory.store_n(bytes_array.span(), 0); // When memory.ensure_length(1); // Then - assert(memory.size() == 32, 'memory should be 32bytes'); + assert_eq!(memory.size(), 32); let value = memory.load_internal(0); - assert(value == 1, 'value should be 1'); + assert_eq!(value, 1); } #[test] @@ -981,35 +958,32 @@ mod tests { let value: u256 = 1; let bytes_array = helpers::u256_to_bytes_array(value); + memory.bytes_len = 32; memory.store_n(bytes_array.span(), 0); // When memory.ensure_length(33); // Then - assert(memory.size() == 64, 'memory should be 64bytes'); + assert_eq!(memory.size(), 64); let value = memory.load_internal(0); - assert(value == 1, 'value should be 1'); + assert_eq!(value, 1); } #[test] - fn test_expand_and_load_should_return_expanded_memory_and_element_and_cost() { + fn test_load_should_return_element() { // Given let mut memory = MemoryTrait::new(); let value: u256 = 1; let bytes_array = helpers::u256_to_bytes_array(value); + memory.bytes_len = 32; memory.store_n(bytes_array.span(), 0); // When - memory.load(32); + let value = memory.load(32); // Then - assert(memory.size() == 64, 'memory should be 64 bytes'); - let value = memory.load_internal(0); - assert(value == 1, 'loaded_element should be 1'); - - let value = memory.load_internal(32); - assert(value == 0, 'value should be 0'); + assert_eq!(value, 0); } #[test] @@ -1022,12 +996,14 @@ mod tests { memory.store_padded_segment(0, 0, bytes); // Then - let len = memory.size(); - assert(len == 0, 'memory should be 0bytes'); + let item_0 = memory.items.get(0); + let item_1 = memory.items.get(1); + assert_eq!(item_0, 0); + assert_eq!(item_1, 0); } #[test] - fn test_store_padded_segment_should_expand_memory() { + fn test_store_padded_segment_should_write_to_memory() { // Given let mut memory = MemoryTrait::new(); @@ -1036,10 +1012,8 @@ mod tests { memory.store_padded_segment(10, 10, bytes); // Then - let len = memory.size(); - assert(len == 32, 'memory should be length 32'); let word = memory.load(10); - assert(word == 0, 'word should be 0'); + assert_eq!(word, 0); } #[test] @@ -1052,9 +1026,6 @@ mod tests { memory.store_padded_segment(0, 5, bytes); // Then - let len = memory.size(); - assert(len == 32, 'memory should be 32bytes'); - let first_word = memory.load_internal(0); assert( first_word == 0x0102030405000000000000000000000000000000000000000000000000000000, @@ -1077,9 +1048,6 @@ mod tests { memory.store_padded_segment(0, 10, bytes); // Then - let len = memory.size(); - assert(len == 32, 'memory should be 32bytes'); - let first_word = memory.load_internal(0); assert( first_word == 0x01020304050000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, @@ -1101,10 +1069,6 @@ mod tests { let bytes = [1, 2, 3, 4, 5].span(); memory.store_padded_segment(5, 10, bytes); - // Then - let len = memory.size(); - assert(len == 32, 'memory should be 32bytes'); - let first_word = memory.load_internal(0); assert( first_word == 0xFFFFFFFFFF01020304050000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, @@ -1128,9 +1092,6 @@ mod tests { memory.store_padded_segment(30, 10, bytes); // Then - let len = memory.size(); - assert(len == 64, 'memory should be 64bytes'); - let first_word = memory.load_internal(0); assert( first_word == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0102, @@ -1156,7 +1117,6 @@ mod tests { // Then assert(memory.items[0] == 0x01, 'Wrong value for word 0'); assert(memory.items[1] == 0x00, 'Wrong value for word 1'); - assert(memory.size() == 32, 'Wrong memory length'); } #[test] fn test_store_byte_should_store_byte_at_offset_2() { @@ -1169,7 +1129,6 @@ mod tests { // Then assert(memory.items[0] == 0xff00, 'Wrong value for word 0'); assert(memory.items[1] == 0x00, 'Wrong value for word 1'); - assert(memory.size() == 32, 'Wrong memory length'); } #[test] @@ -1185,7 +1144,6 @@ mod tests { // Then assert(memory.items[0] == 0xFFFF, 'Wrong value for word 0'); assert(memory.items[1] == 0x01FF, 'Wrong value for word 1'); - assert(memory.size() == 32, 'Wrong memory length'); } #[test] @@ -1200,7 +1158,6 @@ mod tests { assert(memory.items[0] == 0x0, 'Wrong value for word 0'); assert(memory.items[1] == 0x0, 'Wrong value for word 1'); assert(memory.items[2] == 0x01000000000000000000000000000000, 'Wrong value for word 2'); - assert(memory.size() == 64, 'Wrong memory length'); } #[test] @@ -1216,6 +1173,5 @@ mod tests { // Then assert(memory.items[0] == 0x0100, 'Wrong value in word 0'); assert(memory.items[1] == 0xffABffffffffffffffffffffffffffff, 'Wrong value in word 1'); - assert(memory.size() == 32, 'Wrong memory length'); } } diff --git a/crates/evm/src/precompiles/ec_recover.cairo b/crates/evm/src/precompiles/ec_recover.cairo index 7774b3db6..82748a415 100644 --- a/crates/evm/src/precompiles/ec_recover.cairo +++ b/crates/evm/src/precompiles/ec_recover.cairo @@ -80,7 +80,7 @@ mod tests { use evm::precompiles::ec_recover::EcRecover; use evm::stack::StackTrait; use evm::test_utils::setup_test_storages; - use evm::test_utils::{VMBuilderTrait, native_token, other_starknet_address}; + use evm::test_utils::{VMBuilderTrait, MemoryTestUtilsTrait, native_token, other_starknet_address}; use snforge_std::{start_mock_call, test_address}; use utils::helpers::{U256Trait, ToBytes, FromBytes}; @@ -122,7 +122,7 @@ mod tests { .store( 0x456e9aea5e197a1f1af7a3e85a3212fa4049a3ba34c2289b4c860fc0b0c64ef3, 0x0 ); // msg_hash - vm.memory.store(0x1C, 0x20); // v + vm.memory.store_with_expansion(0x1C, 0x20); // v vm .memory .store(0x9242685bf161793cc25603c231bc2f568eb630ea16aa137d2664ac8038825608, 0x40); // r diff --git a/crates/evm/src/precompiles/identity.cairo b/crates/evm/src/precompiles/identity.cairo index c9f602f33..c34f753a0 100644 --- a/crates/evm/src/precompiles/identity.cairo +++ b/crates/evm/src/precompiles/identity.cairo @@ -32,7 +32,7 @@ mod tests { use evm::precompiles::identity::Identity; use evm::stack::StackTrait; use evm::test_utils::{ - VMBuilderTrait, native_token, other_starknet_address, setup_test_storages + VMBuilderTrait, MemoryTestUtilsTrait, native_token, other_starknet_address, setup_test_storages }; use snforge_std::{start_mock_call, test_address}; @@ -64,7 +64,7 @@ mod tests { vm.stack.push(0x4).unwrap(); // address vm.stack.push(0xFFFFFFFF).unwrap(); // gas - vm.memory.store(0x2A, 0x1F); + vm.memory.store_with_expansion(0x2A, 0x1F); start_mock_call::(native_token(), selector!("balanceOf"), 0); vm.exec_staticcall().unwrap(); diff --git a/crates/evm/src/precompiles/sha256.cairo b/crates/evm/src/precompiles/sha256.cairo index 437f910f5..3ba9626fd 100644 --- a/crates/evm/src/precompiles/sha256.cairo +++ b/crates/evm/src/precompiles/sha256.cairo @@ -62,7 +62,7 @@ mod tests { use evm::precompiles::sha256::Sha256; use evm::stack::StackTrait; use evm::test_utils::{ - VMBuilderTrait, native_token, other_starknet_address, setup_test_storages + VMBuilderTrait, MemoryTestUtilsTrait, native_token, other_starknet_address, setup_test_storages }; use snforge_std::{start_mock_call}; use utils::helpers::ToBytes; @@ -165,7 +165,7 @@ mod tests { vm.stack.push(0x2).unwrap(); // address vm.stack.push(0xFFFFFFFF).unwrap(); // gas - vm.memory.store(0xFF, 0x0); + vm.memory.store_with_expansion(0xFF, 0x0); start_mock_call::(native_token(), selector!("balanceOf"), 0); vm.exec_staticcall().unwrap(); diff --git a/crates/evm/src/test_utils.cairo b/crates/evm/src/test_utils.cairo index 19c016792..f64eccd4f 100644 --- a/crates/evm/src/test_utils.cairo +++ b/crates/evm/src/test_utils.cairo @@ -49,6 +49,19 @@ fn register_account(evm_address: EthAddress, starknet_address: ContractAddress) } +#[generate_trait] +impl MemoryUtilsImpl of MemoryTestUtilsTrait { + fn store_with_expansion(ref self: Memory, element: u256, offset: usize) { + self.ensure_length(offset + 32); + self.store(element, offset); + } + + fn store_n_with_expansion(ref self: Memory, elements: Span, offset: usize) { + self.ensure_length(offset + elements.len()); + self.store_n(elements, offset); + } +} + #[derive(Destruct)] struct VMBuilder { vm: VM diff --git a/scripts/gas_debug_call.py b/scripts/gas_debug_call.py index 55ad7fd6b..f9a5a49a7 100644 --- a/scripts/gas_debug_call.py +++ b/scripts/gas_debug_call.py @@ -5,7 +5,9 @@ def process_logs(logs): gas_consumption = {} previous_gas = {} - pattern = re.compile(r"Address (\d+), opcode (\w+), pc (\d+), gas left in call (\d+)") + pattern = re.compile( + r"Address (\d+), opcode (\w+), pc (\d+), gas left in call (\d+)" + ) for line in logs.split("\n"): match = pattern.search(line) @@ -23,7 +25,9 @@ def process_logs(logs): gas_consumption[address] += gas_used previous_gas[address] = gas_left - print(f"{hex(address)} - {pc} - {opcode} --> total gas used: {gas_consumption[address]}") + print( + f"{hex(address)} - {pc} - {opcode} --> total gas used: {gas_consumption[address]}" + ) # Example usage