From ec952fd2cbfd5459bc8c10f507e53534a4a7041a Mon Sep 17 00:00:00 2001 From: xermicus Date: Tue, 26 Mar 2024 15:11:39 +0100 Subject: [PATCH] add another msize test case Signed-off-by: xermicus --- crates/integration/contracts/MSize.sol | 7 ++++ crates/integration/src/lib.rs | 32 +++++++++++++++++-- crates/llvm-context/src/eravm/evm/context.rs | 5 ++- .../llvm-context/src/eravm/evm/return_data.rs | 2 +- 4 files changed, 42 insertions(+), 4 deletions(-) diff --git a/crates/integration/contracts/MSize.sol b/crates/integration/contracts/MSize.sol index b7a22ad..3e73695 100644 --- a/crates/integration/contracts/MSize.sol +++ b/crates/integration/contracts/MSize.sol @@ -6,4 +6,11 @@ contract MSize { size := msize() } } + + function mStore100() public pure returns (uint size) { + assembly { + mstore(100, msize()) + size := msize() + } + } } diff --git a/crates/integration/src/lib.rs b/crates/integration/src/lib.rs index 7d62110..1e50ab9 100644 --- a/crates/integration/src/lib.rs +++ b/crates/integration/src/lib.rs @@ -163,7 +163,7 @@ mod tests { } #[test] - fn msize() { + fn msize_plain() { sol!( #[derive(Debug, PartialEq, Eq)] contract MSize { @@ -175,9 +175,9 @@ mod tests { include_str!("../contracts/MSize.sol"), false, ); + let (instance, export) = mock_runtime::prepare(&code, None); let input = MSize::mSizeCall::new(()).abi_encode(); - let (instance, export) = mock_runtime::prepare(&code, None); let state = crate::mock_runtime::call(State::new(input), &instance, export); assert_eq!(state.output.flags, 0); @@ -187,4 +187,32 @@ mod tests { let received = U256::from_be_bytes::<32>(state.output.data.try_into().unwrap()); assert_eq!(received, expected); } + + #[test] + fn msize_non_word_sized_access() { + sol!( + #[derive(Debug, PartialEq, Eq)] + contract MSize { + function mStore100() public pure returns (uint); + } + ); + let code = crate::compile_blob_with_options( + "MSize", + include_str!("../contracts/MSize.sol"), + false, + ); + let (instance, export) = mock_runtime::prepare(&code, None); + + let input = MSize::mStore100Call::new(()).abi_encode(); + let state = crate::mock_runtime::call(State::new(input), &instance, export); + + assert_eq!(state.output.flags, 0); + + // https://docs.zksync.io/build/developer-reference/differences-with-ethereum.html#mstore-mload + // "Unlike EVM, where the memory growth is in words, on zkEVM the memory growth is counted in bytes." + // "For example, if you write mstore(100, 0) the msize on zkEVM will be 132, but on the EVM it will be 160." + let expected = U256::try_from(132).unwrap(); + let received = U256::from_be_bytes::<32>(state.output.data.try_into().unwrap()); + assert_eq!(received, expected); + } } diff --git a/crates/llvm-context/src/eravm/evm/context.rs b/crates/llvm-context/src/eravm/evm/context.rs index 682ac76..b7f2c19 100644 --- a/crates/llvm-context/src/eravm/evm/context.rs +++ b/crates/llvm-context/src/eravm/evm/context.rs @@ -201,5 +201,8 @@ where .build_ptr_to_int(heap_start, context.xlen_type(), "heap_start")?, "heap_size", )?; - Ok(heap_size.as_basic_value_enum()) + Ok(context + .builder() + .build_int_z_extend(heap_size, context.field_type(), "heap_size_extended")? + .as_basic_value_enum()) } diff --git a/crates/llvm-context/src/eravm/evm/return_data.rs b/crates/llvm-context/src/eravm/evm/return_data.rs index 4655d7d..3f977a5 100644 --- a/crates/llvm-context/src/eravm/evm/return_data.rs +++ b/crates/llvm-context/src/eravm/evm/return_data.rs @@ -89,5 +89,5 @@ where "return_data_copy_memcpy_from_return_data", )?; - Ok(()) + todo!("Build heap GEP to allocate if necessary") }