%%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()