Skip to content

Commit

Permalink
feat: implement add operation on EVM and its related tests
Browse files Browse the repository at this point in the history
  • Loading branch information
leovct committed Jul 16, 2024
1 parent ed2a977 commit 7455b90
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 14 deletions.
42 changes: 42 additions & 0 deletions evm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package main

import "github.com/holiman/uint256"

// IEVM defines the methods that an Ethereum Virtual Machine implementation should have.
type IEVM interface{}

// EVM represents an Ethereum Virtual Machine.
type EVM struct {
stack IStack
memory IMemory
storage IStorage
}

// NewEVM creates and returns a new EVM instance.
func NewEVM() *EVM {
return &EVM{
stack: NewStack(),
memory: NewMemory(),
storage: NewStorage(),
}
}

// Add performs addition of the top two elements on the stack.
// It pops two values from the stack, adds them, and pushes the result back to the stack.
func (e *EVM) Add() error {
a, err := e.stack.Pop()
if err != nil {
return err
}

b, err := e.stack.Pop()
if err != nil {
return err
}

result := new(uint256.Int).Add(a, b)
// This step should never fail because of an overflow.
// Indeed, two elements are popped from the stack and only one is pushed back.
_ = e.stack.Push(result)
return nil
}
100 changes: 100 additions & 0 deletions evm_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package main

import (
"testing"

"github.com/holiman/uint256"
)

func TestNewEVM(t *testing.T) {
evm := NewEVM()
if evm == nil {
t.Error("NewEVM() returned nil")
}
}

func TestAdd(t *testing.T) {
// Create a new EVM.
evm := NewEVM()

// Push some elements to the stack.
// The stack should be equal to [0x1, 0x2, 0x3].
evm.stack.Push(uint256.NewInt(1))
evm.stack.Push(uint256.NewInt(2))
evm.stack.Push(uint256.NewInt(3))

// Add the two elements at the top of the stack.
// The stack should be equal to [0x1, 0x5].
err := evm.Add()
if err != nil {
t.Errorf("Add() returned an unexpected error: %v", err)
}

// Pop the element from the stack to check the result.
result, err := evm.stack.Pop()
expectedResult := uint256.NewInt(5)
if err != nil {
t.Errorf("Pop() returned an unexpected error: %v", err)
}
if !result.Eq(expectedResult) {
t.Errorf("Expected %v, got %v", expectedResult, result)
}
}

func TestAddOnEmptyStack(t *testing.T) {
// Create a new EVM.
evm := NewEVM()

// Try to add the two elements at the top of the stack.
err := evm.Add()
if err == nil {
t.Error("Add() should return an error because there are no elements in the stack")
}
}

func TestAddOnOneElementStack(t *testing.T) {
// Create a new EVM.
evm := NewEVM()

// Add one element to the stack.
// The stack should be equal to [0x1].
evm.stack.Push(uint256.NewInt(1))

// Try to add the two elements at the top of the stack.
err := evm.Add()
if err == nil {
t.Error("Add() should return an error because there is only one element in the stack")
}
}

func TestAddOnFullStack(t *testing.T) {
// Create a new EVM.
evm := NewEVM()

// Push 1024 elements to the stack.
// The stack should contain 1024 0x1 elements.
for i := 0; i < MAX_STACK_SIZE; i++ {
err := evm.stack.Push(uint256.NewInt(1))
if err != nil {
t.Errorf("Push() returned an unexpected error on iteration %d: %v", i, err)
}
}

// Try to add the two elements at the top of the stack.
err := evm.Add()
if err != nil {
t.Error("Add() should return an error because the stack is full")
}
}

func TestMul(t *testing.T) {
// TODO
}

func TestSub(t *testing.T) {
// TODO
}

func TestDiv(t *testing.T) {
// TODO
}
14 changes: 0 additions & 14 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,3 @@ func main() {
evm := NewEVM()
fmt.Println("EVM:", evm)
}

type EVM struct {
Stack IStack
Memory IMemory
Storage IStorage
}

func NewEVM() *EVM {
return &EVM{
Stack: NewStack(),
Memory: NewMemory(),
Storage: NewStorage(),
}
}

0 comments on commit 7455b90

Please sign in to comment.