Memory#

The Memory is a list of bytes. Each byte can be accessed individually.

Similar to RAM, it starts of by being completely empty. It is also volatile, which means that after execution the memory is reset.

Each memory cell can hold 1 byte (8 bits). A number between 0 and 255.

title

We will represent Memory as a simple list that can be accessed by an index or offset.

An offset of 2 would mean that we get the byte stored at index 2. Combined with a size we can get a block of bytes. Offset 2 and size 5 would return the bytes from index 2 to index 7.

class SimpleMemory:
    def __init__(self): self.memory = []
        
    def access(self, offset, size): return self.memory[offset:offset+size]
    def load  (self, offset):       return self.access(offset, 32)
    def store (self, offset, value): self.memory[offset:offset+len(value)] = value

Expanding the size of Memory consumes gas non-linearly. Making it more costly to create larger and larger Memory space.

Lets add the gas expansion calculation to the Memory

class Memory(SimpleMemory):
    def store(self, offset, value):
        memory_expansion_cost = 0
        
        if len(self.memory) <= offset + len(value):
            
            expansion_size = 0
            
            # initialize memory with 32 zeros if it is empty
            if len(self.memory) == 0:
                expansion_size = 32
                self.memory = [0x00 for _ in range(32)]
                
            # extend memory more if needed
            if len(self.memory) < offset + len(value):
                expansion_size += offset + len(value) - len(self.memory)
                self.memory.extend([0x00] * expansion_size)
                
            memory_expansion_cost = expansion_size**2 # simplified!
                
        super().store(offset, value)
        return memory_expansion_cost

Lets create a some Memory

memory = Memory()

We store 4 values at offset 0

memory.store(0, [0x01, 0x02, 0x03, 0x04]);

load will always return 32 bytes if it can

memory.load(0)
[1,
 2,
 3,
 4,
 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]

Advanced#

This is the actual way how the gas cost for a memory expansion is calculated.

def calc_memory_expansion_gas(memory_byte_size):
    memory_size_word = (memory_byte_size + 31) / 32
    memory_cost = (memory_size_word ** 2) / 512 + (3 * memory_size_word)
    return round(memory_cost)