diff --git a/parsing.go b/parsing.go
index 4c3f1187e4f964a53c8b6a8624e0f4ccb9c5223d..b97d77f3e4e2efb5d7ea4f69f251097282bea928 100644
--- a/parsing.go
+++ b/parsing.go
@@ -10,50 +10,29 @@ import (
 
 // Op codes
 var OpCodes = map[string]string{
-  "STOP":       "0",
-  "PUSH":       "48",  // 0x30
-  "POP":        "49",  // 0x31
-  "LOAD":       "54",  // 0x36
-
-  /* OLD VM OPCODES
-  "ADD":        "16",  // 0x10
-  "SUB":        "17",  // 0x11
-  "MUL":        "18",  // 0x12
-  "DIV":        "19",  // 0x13
-  "SDIV":       "20",  // 0x14
-  "MOD":        "21",  // 0x15
-  "SMOD":       "22",  // 0x16
-  "EXP":        "23",  // 0x17
-  "NEG":        "24",  // 0x18
-  "LT":         "32",  // 0x20
-  "LE":         "33",  // 0x21
-  "GT":         "34",  // 0x22
-  "GE":         "35",  // 0x23
-  "EQ":         "36",  // 0x24
-  "NOT":        "37",  // 0x25
-  "SHA256":     "48",  // 0x30
-  "RIPEMD160":  "49",  // 0x31
-  "ECMUL":      "50",  // 0x32
-  "ECADD":      "51",  // 0x33
-  "SIGN":       "52",  // 0x34
-  "RECOVER":    "53",  // 0x35
-  "COPY":       "64",  // 0x40
-  "ST":         "65",  // 0x41
-  "LD":         "66",  // 0x42
-  "SET":        "67",  // 0x43
-  "JMP":        "80",  // 0x50
-  "JMPI":       "81",  // 0x51
-  "IND":        "82",  // 0x52
-  "EXTRO":      "96",  // 0x60
-  "BALANCE":    "97",  // 0x61
-  "MKTX":       "112", // 0x70
-  "DATA":       "128", // 0x80
-  "DATAN":      "129", // 0x81
-  "MYADDRESS":  "144", // 0x90
-  "BLKHASH":    "145", // 0x91
-  "COINBASE":   "146", // 0x92
-  "SUICIDE":    "255", // 0xff
-  */
+  "STOP":        "0",
+  "ADD":         "1",
+  "MUL":         "2",
+  "SUB":         "3",
+  "DIV":         "4",
+  "SDIV":        "5",
+  "MOD":         "6",
+  "SMOD":        "7",
+  "EXP":         "8",
+  "NEG":         "9",
+  "LT":         "10",
+  "LE":         "11",
+  "GT":         "12",
+  "GE":         "13",
+  "EQ":         "14",
+  "NOT":        "15",
+  "MYADDRESS":  "16",
+  "TXSENDER":   "17",
+
+
+  "PUSH":       "48",
+  "POP":        "49",
+  "LOAD":       "54",
 }
 
 
diff --git a/vm.go b/vm.go
index d7e3f77cf6538ef3d08c494ad594586cd601149c..9e1e83b0b5ee5b829c98baf6261afd987c2437d0 100644
--- a/vm.go
+++ b/vm.go
@@ -12,46 +12,28 @@ import (
 // Op codes
 const (
   oSTOP       int = 0x00
+  oADD        int = 0x01
+  oMUL        int = 0x02
+  oSUB        int = 0x03
+  oDIV        int = 0x04
+  oSDIV       int = 0x05
+  oMOD        int = 0x06
+  oSMOD       int = 0x07
+  oEXP        int = 0x08
+  oNEG        int = 0x09
+  oLT         int = 0x0a
+  oLE         int = 0x0b
+  oGT         int = 0x0c
+  oGE         int = 0x0d
+  oEQ         int = 0x0e
+  oNOT        int = 0x0f
+  oMYADDRESS  int = 0x10
+  oTXSENDER   int = 0x11
+
+
   oPUSH       int = 0x30
   oPOP        int = 0x31
   oLOAD       int = 0x36
-  /*
-  oADD        int = 0x10
-  oSUB        int = 0x11
-  oMUL        int = 0x12
-  oDIV        int = 0x13
-  oSDIV       int = 0x14
-  oMOD        int = 0x15
-  oSMOD       int = 0x16
-  oEXP        int = 0x17
-  oNEG        int = 0x18
-  oLT         int = 0x20
-  oLE         int = 0x21
-  oGT         int = 0x22
-  oGE         int = 0x23
-  oEQ         int = 0x24
-  oNOT        int = 0x25
-  oSHA256     int = 0x30
-  oRIPEMD160  int = 0x31
-  oECMUL      int = 0x32
-  oECADD      int = 0x33
-  oSIGN       int = 0x34
-  oRECOVER    int = 0x35
-  oCOPY       int = 0x40
-  oST         int = 0x41
-  oLD         int = 0x42
-  oSET        int = 0x43
-  oJMP        int = 0x50
-  oJMPI       int = 0x51
-  oIND        int = 0x52
-  oEXTRO      int = 0x60
-  oBALANCE    int = 0x61
-  oMKTX       int = 0x70
-  oDATA       int = 0x80
-  oDATAN      int = 0x81
-  oMYADDRESS  int = 0x90
-  oSUICIDE    int = 0xff
-  */
 )
 
 type OpType int
@@ -79,9 +61,21 @@ func (st *Stack) Pop() string {
   return str
 }
 
+func (st *Stack) Popn() (*big.Int, *big.Int) {
+  s := len(st.data)
+
+  strs := st.data[s-2:]
+  st.data = st.data[:s-2]
+
+  return Big(strs[0]), Big(strs[1])
+}
+
 func (st *Stack) Push(d string) {
   st.data = append(st.data, d)
 }
+func (st *Stack) Print() {
+  fmt.Println(st.data)
+}
 
 type Vm struct {
   // Stack
@@ -96,7 +90,7 @@ func NewVm() *Vm {
 
 func (vm *Vm) ProcContract(tx *Transaction, block *Block, cb TxCallback) {
   // Instruction pointer
-  iptr := 0
+  pc := 0
 
   contract := block.GetContract(tx.Hash())
   if contract == nil {
@@ -104,164 +98,144 @@ func (vm *Vm) ProcContract(tx *Transaction, block *Block, cb TxCallback) {
     return
   }
 
+  Pow256 := BigPow(2, 256)
+
   fmt.Printf("#   op   arg\n")
 out:
   for {
     // The base big int for all calculations. Use this for any results.
     base := new(big.Int)
-    base.SetString("0",0) // so it doesn't whine about it
     // XXX Should Instr return big int slice instead of string slice?
     // Get the next instruction from the contract
-    op, args, _ := Instr(contract.state.Get(string(Encode(uint32(iptr)))))
+    //op, _, _ := Instr(contract.state.Get(string(Encode(uint32(pc)))))
+    op, _, _ := Instr(contract.state.Get(string(NumberToBytes(uint64(pc), 32))))
+
+    if !cb(0) { break }
 
     if Debug {
-      fmt.Printf("%-3d %-4d %v\n", iptr, op, args)
+      fmt.Printf("%-3d %-4d\n", pc, op)
     }
 
     switch op {
+    case oADD:
+      x, y := vm.stack.Popn()
+      // (x + y) % 2 ** 256
+      base.Add(x, y)
+      base.Mod(base, Pow256)
+      // Pop result back on the stack
+      vm.stack.Push(base.String())
+    case oSUB:
+      x, y := vm.stack.Popn()
+      // (x - y) % 2 ** 256
+      base.Sub(x, y)
+      base.Mod(base, Pow256)
+      // Pop result back on the stack
+      vm.stack.Push(base.String())
+    case oMUL:
+      x, y := vm.stack.Popn()
+      // (x * y) % 2 ** 256
+      base.Mul(x, y)
+      base.Mod(base, Pow256)
+      // Pop result back on the stack
+      vm.stack.Push(base.String())
+    case oDIV:
+      x, y := vm.stack.Popn()
+      // floor(x / y)
+      base.Div(x, y)
+      // Pop result back on the stack
+      vm.stack.Push(base.String())
+    case oSDIV:
+      x, y := vm.stack.Popn()
+      // n > 2**255
+      if x.Cmp(Pow256) > 0 { x.Sub(Pow256, x) }
+      if y.Cmp(Pow256) > 0 { y.Sub(Pow256, y) }
+      z := new(big.Int)
+      z.Div(x, y)
+      if z.Cmp(Pow256) > 0 { z.Sub(Pow256, z) }
+      // Push result on to the stack
+      vm.stack.Push(z.String())
+    case oMOD:
+      x, y := vm.stack.Popn()
+      base.Mod(x, y)
+      vm.stack.Push(base.String())
+    case oSMOD:
+      x, y := vm.stack.Popn()
+      // n > 2**255
+      if x.Cmp(Pow256) > 0 { x.Sub(Pow256, x) }
+      if y.Cmp(Pow256) > 0 { y.Sub(Pow256, y) }
+      z := new(big.Int)
+      z.Mod(x, y)
+      if z.Cmp(Pow256) > 0 { z.Sub(Pow256, z) }
+      // Push result on to the stack
+      vm.stack.Push(z.String())
+    case oEXP:
+      x, y := vm.stack.Popn()
+      base.Exp(x, y, Pow256)
+
+      vm.stack.Push(base.String())
+    case oNEG:
+      base.Sub(Pow256, Big(vm.stack.Pop()))
+      vm.stack.Push(base.String())
+    case oLT:
+      x, y := vm.stack.Popn()
+      // x < y
+      if x.Cmp(y) < 0 {
+        vm.stack.Push("1")
+      } else {
+        vm.stack.Push("0")
+      }
+    case oLE:
+      x, y := vm.stack.Popn()
+      // x <= y
+      if x.Cmp(y) < 1 {
+        vm.stack.Push("1")
+      } else {
+        vm.stack.Push("0")
+      }
+    case oGT:
+      x, y := vm.stack.Popn()
+      // x > y
+      if x.Cmp(y) > 0 {
+        vm.stack.Push("1")
+      } else {
+        vm.stack.Push("0")
+      }
+    case oGE:
+      x, y := vm.stack.Popn()
+      // x >= y
+      if x.Cmp(y) > -1 {
+        vm.stack.Push("1")
+      } else {
+        vm.stack.Push("0")
+      }
+    case oNOT:
+      x, y := vm.stack.Popn()
+      // x != y
+      if x.Cmp(y) != 0 {
+        vm.stack.Push("1")
+      } else {
+        vm.stack.Push("0")
+      }
+    case oMYADDRESS:
+      vm.stack.Push(string(tx.Hash()))
+    case oTXSENDER:
+      vm.stack.Push(tx.sender)
     case oPUSH:
       // Get the next entry and pushes the value on the stack
-      iptr++
-      vm.stack.Push(contract.state.Get(string(Encode(uint32(iptr)))))
+      pc++
+      vm.stack.Push(contract.state.Get(string(NumberToBytes(uint64(pc), 32))))
     case oPOP:
       // Pop current value of the stack
       vm.stack.Pop()
     case oLOAD:
       // Load instruction X on the stack
       i, _ := strconv.Atoi(vm.stack.Pop())
-      vm.stack.Push(contract.state.Get(string(Encode(uint32(i)))))
+      vm.stack.Push(contract.state.Get(string(NumberToBytes(uint64(i), 32))))
     case oSTOP:
       break out
     }
-    iptr++
+    pc++
   }
-}
 
-/*
-type Vm struct {
-  // Memory stack
-  stack map[string]string
-  memory map[string]map[string]string
-}
-
-func NewVm() *Vm {
-  //stackSize := uint(256)
-
-  return &Vm{
-    stack: make(map[string]string),
-    memory: make(map[string]map[string]string),
-  }
-}
-
-func (vm *Vm) RunTransaction(tx *Transaction, cb TxCallback) {
-  if Debug {
-    fmt.Printf(`
-# processing Tx (%v)
-# fee = %f, ops = %d, sender = %s, value = %d
-  `, tx.addr, float32(tx.fee) / 1e8, len(tx.data), tx.sender, tx.value)
-  }
-
-  vm.stack = make(map[string]string)
-  vm.stack["0"] = tx.sender
-  vm.stack["1"] = "100"  //int(tx.value)
-  vm.stack["1"] = "1000" //int(tx.fee)
-  // Stack pointer
-  stPtr := 0
-
-  //vm.memory[tx.addr] = make([]int, 256)
-  vm.memory[tx.addr] = make(map[string]string)
-
-  // Define instruction 'accessors' for the instruction, which makes it more readable
-  // also called register values, shorthanded as Rx/y/z. Memory address are shorthanded as Mx/y/z.
-  // Instructions are shorthanded as Ix/y/z
-  x := 0; y := 1; z := 2; //a := 3; b := 4; c := 5
-out:
-  for stPtr < len(tx.data) {
-    // The base big int for all calculations. Use this for any results.
-    base := new(big.Int)
-    // XXX Should Instr return big int slice instead of string slice?
-    op, args, _ := Instr(tx.data[stPtr])
-
-    if Debug {
-      fmt.Printf("%-3d %d %v\n", stPtr, op, args)
-    }
-
-    opType     := OpType(tNorm)
-    // Determine the op type (used for calculating fees by the block manager)
-    switch op {
-    case oEXTRO, oBALANCE:
-      opType = tExtro
-    case oSHA256, oRIPEMD160, oECMUL, oECADD: // TODO add rest
-      opType = tCrypto
-    }
-
-    // If the callback yielded a negative result abort execution
-    if !cb(opType) { break out }
-
-    nptr := stPtr
-    switch op {
-    case oSTOP:
-      fmt.Println("exiting (oSTOP), idx =", nptr)
-
-      break out
-    case oADD:
-      // (Rx + Ry) % 2 ** 256
-      base.Add(Big(vm.stack[args[ x ]]), Big(vm.stack[args[ y ]]))
-      base.Mod(base, big.NewInt(int64(math.Pow(2, 256))))
-      // Set the result to Rz
-      vm.stack[args[ z ]] = base.String()
-    case oSUB:
-      // (Rx - Ry) % 2 ** 256
-      base.Sub(Big(vm.stack[args[ x ]]), Big(vm.stack[args[ y ]]))
-      base.Mod(base, big.NewInt(int64(math.Pow(2, 256))))
-      // Set the result to Rz
-      vm.stack[args[ z ]] = base.String()
-    case oMUL:
-      // (Rx * Ry) % 2 ** 256
-      base.Mul(Big(vm.stack[args[ x ]]), Big(vm.stack[args[ y ]]))
-      base.Mod(base, big.NewInt(int64(math.Pow(2, 256))))
-      // Set the result to Rz
-      vm.stack[args[ z ]] = base.String()
-    case oDIV:
-      // floor(Rx / Ry)
-      base.Div(Big(vm.stack[args[ x ]]), Big(vm.stack[args[ y ]]))
-      // Set the result to Rz
-      vm.stack[args[ z ]] = base.String()
-    case oSET:
-      // Set the (numeric) value at Iy to Rx
-      vm.stack[args[ x ]] = args[ y ]
-    case oLD:
-      // Load the value at Mx to Ry
-      vm.stack[args[ y ]] = vm.memory[tx.addr][vm.stack[args[ x ]]]
-    case oLT:
-      cmp := Big(vm.stack[args[ x ]]).Cmp( Big(vm.stack[args[ y ]]) )
-      // Set the result as "boolean" value to Rz
-      if  cmp < 0 { // a < b
-        vm.stack[args[ z ]] = "1"
-      } else {
-        vm.stack[args[ z ]] = "0"
-      }
-    case oJMP:
-      // Set the instruction pointer to the value at Rx
-      ptr, _ := strconv.Atoi( vm.stack[args[ x ]] )
-      nptr = ptr
-    case oJMPI:
-      // Set the instruction pointer to the value at Ry if Rx yields true
-      if vm.stack[args[ x ]] != "0" {
-        ptr, _ := strconv.Atoi( vm.stack[args[ y ]] )
-        nptr = ptr
-      }
-    default:
-      fmt.Println("Error op", op)
-      break
-    }
-
-    if stPtr == nptr {
-      stPtr++
-    } else {
-      stPtr = nptr
-      if Debug { fmt.Println("... JMP", nptr, "...") }
-    }
-  }
+  vm.stack.Print()
 }
-*/
diff --git a/vm_test.go b/vm_test.go
index fe0358a42a7a618941097b13df5e8b7c61407a1d..efcd875cdd38c6ad5d50ace0d9cb38bb237cc52b 100644
--- a/vm_test.go
+++ b/vm_test.go
@@ -7,23 +7,66 @@ import (
 
 
 func TestVm(t *testing.T) {
+  InitFees()
+
   db, _ := NewMemDatabase()
   Db = db
 
-  ctrct := NewTransaction("", 20, []string{
-    "PUSH",
-    "1a2f2e",
-    "PUSH",
-    "hallo",
+  ctrct := NewTransaction("", 200000000, []string{
+    "PUSH", "1a2f2e",
+    "PUSH", "hallo",
     "POP",   // POP hallo
-    "PUSH",
-    "3",
+    "PUSH", "3",
     "LOAD",  // Load hallo back on the stack
+
+    "PUSH", "1",
+    "PUSH", "2",
+    "ADD",
+
+    "PUSH", "2",
+    "PUSH", "1",
+    "SUB",
+
+    "PUSH", "100000000000000000000000",
+    "PUSH", "10000000000000",
+    "SDIV",
+
+    "PUSH", "105",
+    "PUSH", "200",
+    "MOD",
+
+    "PUSH", "100000000000000000000000",
+    "PUSH", "10000000000000",
+    "SMOD",
+
+    "PUSH", "5",
+    "PUSH", "10",
+    "LT",
+
+    "PUSH", "5",
+    "PUSH", "5",
+    "LE",
+
+    "PUSH", "50",
+    "PUSH", "5",
+    "GT",
+
+    "PUSH", "5",
+    "PUSH", "5",
+    "GE",
+
+    "PUSH", "10",
+    "PUSH", "10",
+    "NOT",
+
+    "MYADDRESS",
+    "TXSENDER",
+
     "STOP",
   })
   tx := NewTransaction("1e8a42ea8cce13", 100, []string{})
 
-  block := CreateBlock("", 0, "", "", 0, 0, "", []*Transaction{ctrct, tx})
+  block := CreateBlock("", 0, "", "c014ba53", 0, 0, "", []*Transaction{ctrct, tx})
   db.Put(block.Hash(), block.MarshalRlp())
 
   bm := NewBlockManager()