%%capture
%run 02_stack.ipynb
%run 03_memory.ipynb
%run 04_storage.ipynb
%run 05_opcodes.ipynb
%run 06_stop.ipynb
%run 07_math.ipynb
%run push.ipynb
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
File /tmp/ipykernel_5450/1192403925.py:1
----> 1 print(stack.pop())

TypeError: pop() missing 1 required positional argument: 'n'
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[1], line 1
----> 1 get_ipython().run_line_magic('run', '02_stack.ipynb')
      2 get_ipython().run_line_magic('run', '03_memory.ipynb')
      3 get_ipython().run_line_magic('run', '04_storage.ipynb')

File ~/python3.8/lib/python3.8/site-packages/IPython/core/interactiveshell.py:2417, in InteractiveShell.run_line_magic(self, magic_name, line, _stack_depth)
   2415     kwargs['local_ns'] = self.get_local_scope(stack_depth)
   2416 with self.builtin_trap:
-> 2417     result = fn(*args, **kwargs)
   2419 # The code below prevents the output from being displayed
   2420 # when using magics with decodator @output_can_be_silenced
   2421 # when the last Python token in the expression is a ';'.
   2422 if getattr(fn, magic.MAGIC_OUTPUT_CAN_BE_SILENCED, False):

File ~/python3.8/lib/python3.8/site-packages/IPython/core/magics/execution.py:722, in ExecutionMagics.run(self, parameter_s, runner, file_finder)
    720     with preserve_keys(self.shell.user_ns, '__file__'):
    721         self.shell.user_ns['__file__'] = filename
--> 722         self.shell.safe_execfile_ipy(filename, raise_exceptions=True)
    723     return
    725 # Control the response to exit() calls made by the script being run

File ~/python3.8/lib/python3.8/site-packages/IPython/core/interactiveshell.py:2939, in InteractiveShell.safe_execfile_ipy(self, fname, shell_futures, raise_exceptions)
   2937 result = self.run_cell(cell, silent=True, shell_futures=shell_futures)
   2938 if raise_exceptions:
-> 2939     result.raise_error()
   2940 elif not result.success:
   2941     break

File ~/python3.8/lib/python3.8/site-packages/IPython/core/interactiveshell.py:268, in ExecutionResult.raise_error(self)
    266     raise self.error_before_exec
    267 if self.error_in_exec is not None:
--> 268     raise self.error_in_exec

    [... skipping hidden 1 frame]

File /tmp/ipykernel_5450/1192403925.py:1
----> 1 print(stack.pop())

TypeError: pop() missing 1 required positional argument: 'n'

EVM#

Now we are going to put everything together.

Program Counter#

The program counter indexes into the bytecode. It tells the EVM which opcode to execute next

class EVM:
    def __init__(self,
                 program,
                 gas,
                 value,
                 calldata=[]):
        self.pc      = 0
        self.stack   = Stack()
        self.memory  = Memory()
        self.storage = Storage()
        
        self.program  = program
        self.gas      = gas
        self.value    = value
        self.calldata = calldata
        
        self.stop_flag   = False
        self.revert_flag = False
        
        self.returndata = []
        self.logs       = []
        
    def peek(self): return self.program[self.pc]
    
    def gas_dec(self, amount):
        if self.gas - amount < 0: 
            raise Exception("out of gas")
        self.gas -= amount

    
    def should_execute_next_opcode(self):
        if self.pc > len(self.program)-1: return False
        if self.stop_flag               : return False
        if self.revert_flag             : return False
        
        return True
    
    def run(self):
        while self.should_execute_next_opcode():
            op = self.program[self.pc]
            
            if op == STOP: stop(self)
                
            if op == ADD: add(self)

                
            if op == PUSH1: _push(self, 1)
        
    def reset(self):
        self.pc      = 0
        self.stack   = Stack()
        self.memory  = Memory()
        self.storage = Storage()