Skip to content

Commit

Permalink
chore(docs): add doctests for some evm modules
Browse files Browse the repository at this point in the history
  • Loading branch information
Jon-Becker committed Nov 13, 2023
1 parent ffc98c2 commit bef56d9
Show file tree
Hide file tree
Showing 8 changed files with 681 additions and 421 deletions.
6 changes: 3 additions & 3 deletions common/src/ether/evm/core/log.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use ethers::prelude::U256;

/// The [`Log`] struct represents a log emitted by a `LOG0-LOG4` opcode.
#[derive(Clone, Debug)]
pub struct Log {
pub index: u128,
Expand All @@ -8,9 +9,8 @@ pub struct Log {
}

impl Log {
// Implements a new log with the given index and "emits"
// the log at the given index.
/// Creates a new [`Log`] with the given log index, topics, and hex data.
pub fn new(index: u128, topics: Vec<U256>, data: &[u8]) -> Log {
Log { index: index, topics: topics, data: data.to_vec() }
Log { index, topics, data: data.to_vec() }
}
}
221 changes: 214 additions & 7 deletions common/src/ether/evm/core/memory.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,40 @@
/// The [`Memory`] struct represents the memory of an EVM.
#[derive(Clone, Debug)]
pub struct Memory {
pub memory: Vec<u8>,
// TODO: add bit-tracking for memory
}

impl Memory {
// Repr as a [u8]
/// Creates a new [`Memory`] with an empty memory vector.
pub fn new() -> Memory {
Memory { memory: Vec::new() }
}

// get the size of the memory in bytes
/// Gets the current size of the memory in bytes.
///
/// ```
/// use heimdall_common::ether::evm::core::memory::Memory;
///
/// let memory = Memory::new();
/// assert_eq!(memory.size(), 0);
/// ```
pub fn size(&self) -> u128 {
self.memory.len() as u128
}

// extend the memory to a given size
/// Extends the memory to the given size, if necessary. \
/// This is called when a memory store is performed, and the memory must be extended to fit the
/// value.
///
/// ```
/// use heimdall_common::ether::evm::core::memory::Memory;
///
/// let mut memory = Memory::new();
/// assert_eq!(memory.size(), 0);
/// memory.extend(0, 32);
/// assert_eq!(memory.size(), 32);
/// ```
pub fn extend(&mut self, offset: u128, size: u128) {
// Calculate the new size of the memory
let new_mem_size = (offset + size + 31) / 32 * 32;
Expand All @@ -26,7 +46,16 @@ impl Memory {
}
}

// stores a bytearray in the memory at offset
/// Store the given bytes in the memory at the given offset, with a fixed size.
/// May extend the memory if necessary.
///
/// ```
/// use heimdall_common::ether::evm::core::memory::Memory;
///
/// let mut memory = Memory::new();
/// memory.store(0, 32, &[0xff]);
/// assert_eq!(memory.read(0, 32), vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff]);
/// ```
pub fn store(&mut self, mut offset: usize, mut size: usize, value: &[u8]) {
// Cap offset and size to 2**16
offset = offset.min(65536);
Expand Down Expand Up @@ -54,7 +83,17 @@ impl Memory {
self.memory.splice(offset..offset + size, value);
}

// read a value from the memory at the given offset, with a fixed size
/// Read the given number of bytes from the memory at the given offset.
/// If the offset + size is greater than the current size of the memory, null bytes will be
/// appended to the value.
///
/// ```
/// use heimdall_common::ether::evm::core::memory::Memory;
///
/// let mut memory = Memory::new();
/// memory.store(0, 32, &[0xff]);
/// assert_eq!(memory.read(0, 32), vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff]);
/// ```
pub fn read(&self, offset: usize, size: usize) -> Vec<u8> {
// Cap size to 2**16 and offset to 2**16 for optimization
let size = size.min(65536);
Expand All @@ -75,14 +114,31 @@ impl Memory {
}
}

// calculate the current memory cost
/// Calculate the current memory cost
///
/// ```
/// use heimdall_common::ether::evm::core::memory::Memory;
///
/// let mut memory = Memory::new();
/// memory.store(0, 32, &[0xff]);
/// assert_eq!(memory.memory_cost(), 3);
/// ```
pub fn memory_cost(&self) -> u128 {
// Calculate the new size of the memory
let memory_word_size = (self.size() + 31) / 32;
(memory_word_size.pow(2)) / 512 + (3 * memory_word_size)
}

// calculate the memory cost of extending the memory to a given size
/// calculate the memory cost of extending the memory to a given size
///
/// ```
/// use heimdall_common::ether::evm::core::memory::Memory;
///
/// let mut memory = Memory::new();
/// memory.store(0, 32, &[0xff]);
/// assert_eq!(memory.expansion_cost(0, 32), 0);
/// assert_eq!(memory.expansion_cost(0, 64), 3);
/// ```
pub fn expansion_cost(&self, offset: usize, size: usize) -> u128 {
// Calculate the new size of the memory
let new_memory_word_size = ((offset + size + 31) / 32) as u128;
Expand All @@ -94,3 +150,154 @@ impl Memory {
}
}
}

#[cfg(test)]
mod tests {
use crate::{ether::evm::core::memory::Memory, utils::strings::decode_hex};

#[test]
fn test_mstore_simple() {
let mut memory = Memory::new();
memory.store(
0,
32,
&decode_hex("00000000000000000000000000000000000000000000000000000000000000ff")
.unwrap(),
);
assert_eq!(
memory.memory,
decode_hex("00000000000000000000000000000000000000000000000000000000000000ff").unwrap()
);
}

#[test]
fn test_mstore_extend() {
let mut memory = Memory::new();
memory.store(0, 32, &[0xff]);
assert_eq!(
memory.memory,
decode_hex("00000000000000000000000000000000000000000000000000000000000000ff").unwrap()
);
}

#[test]
fn test_mstore_offset() {
let mut memory = Memory::new();
memory.store(4, 32, &[0xff]);
assert_eq!(
memory.memory,
decode_hex("0000000000000000000000000000000000000000000000000000000000000000000000ff00000000000000000000000000000000000000000000000000000000").unwrap()
);
}

#[test]
fn test_mstore_large_nonstandard_offset() {
let mut memory = Memory::new();
memory.store(34, 32, &[0xff]);
assert_eq!(
memory.memory,
decode_hex("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ff000000000000000000000000000000000000000000000000000000000000").unwrap()
);
}

#[test]
fn test_mstore8() {
let mut memory = Memory::new();
memory.store(0, 1, &[0xff]);
assert_eq!(
memory.memory,
decode_hex("ff00000000000000000000000000000000000000000000000000000000000000").unwrap()
);
}

#[test]
fn test_mstore_large_offser() {
let mut memory = Memory::new();
memory.store(255, 32, &[0xff]);
assert_eq!(
memory.memory,
decode_hex("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ff00").unwrap()
);
}

#[test]
fn test_mload_simple() {
let mut memory = Memory::new();
memory.store(
0,
32,
&decode_hex("11223344556677889900aabbccddeeff11223344556677889900aabbccddeeff")
.unwrap(),
);
assert_eq!(
memory.read(0, 32),
decode_hex("11223344556677889900aabbccddeeff11223344556677889900aabbccddeeff").unwrap()
);
}

#[test]
fn test_mload_pad_one() {
let mut memory = Memory::new();
memory.store(
0,
32,
&decode_hex("11223344556677889900aabbccddeeff11223344556677889900aabbccddeeff")
.unwrap(),
);
assert_eq!(
memory.read(1, 32),
decode_hex("223344556677889900aabbccddeeff11223344556677889900aabbccddeeff00").unwrap()
);
}

#[test]
fn test_mload_pad_large() {
let mut memory = Memory::new();
memory.store(
0,
32,
&decode_hex("11223344556677889900aabbccddeeff11223344556677889900aabbccddeeff")
.unwrap(),
);
assert_eq!(
memory.read(31, 32),
decode_hex("ff00000000000000000000000000000000000000000000000000000000000000").unwrap()
);
}

#[test]
fn test_memory_cost() {
let mut memory = Memory::new();
memory.store(
0,
32,
&decode_hex("11223344556677889900aabbccddeeff11223344556677889900aabbccddeeff")
.unwrap(),
);
assert_eq!(memory.memory_cost(), 3);
}

#[test]
fn test_memory_cost_2() {
let mut memory = Memory::new();
memory.store(
32 * 32,
32,
&decode_hex("11223344556677889900aabbccddeeff11223344556677889900aabbccddeeff")
.unwrap(),
);
assert_eq!(memory.memory_cost(), 101);
}

#[test]
fn test_expansion_cost() {
let memory = Memory::new();
assert_eq!(memory.expansion_cost(0, 32), 3);
}

#[test]
fn test_expansion_cost_2() {
let memory = Memory::new();
assert_eq!(memory.expansion_cost(32 * 32, 32), 101);
}
}
Loading

0 comments on commit bef56d9

Please sign in to comment.