diff --git a/src/lib.rs b/src/lib.rs index a483eaf..9da1de3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -142,7 +142,15 @@ impl Stack { 0x50 => { self.pc += 1; match opcode { + 0x51 => self.mload(), 0x52 => self.mstore(), + 0x56 => self.jump(), + 0x57 => { + self.jump_i(); + } + 0x5b => { + self.jump_dest(); + } _ => panic!("unimplemented {:x}", opcode), } } @@ -152,6 +160,30 @@ impl Stack { self.push_arbitrary(&code[self.pc + 1..self.pc + 1 + n]); self.pc += 1 + n; } + 0x80 => { + // 0x8x dup + let l = self.stack.len(); + if opcode > 0x7f { + self.stack.push(self.stack[l - (opcode - 0x7f) as usize]); + } else { + self.stack.push(self.stack[(0x7f - opcode) as usize]); + } + self.pc += 1; + } + 0x90 => { + // 0x9x swap + let l = self.stack.len(); + let pos; + if opcode > 0x8e { + pos = l - (opcode - 0x8e) as usize; + } else { + pos = (0x8e - opcode) as usize; + } + let tmp = self.stack[pos]; + self.stack[pos] = self.stack[l - 1]; + self.stack[l - 1] = tmp; + self.pc += 1; + } 0xf0 => { if opcode == 0xf3 { let pos_to_return = u256_to_u64(self.pop()) as usize; @@ -255,6 +287,12 @@ impl Stack { let mut new_bytes: Vec = vec![0; size]; self.mem.append(&mut new_bytes); } + fn mload(&mut self) { + let pos = u256_to_u64(self.pop()) as usize; + self.extend_mem(pos as usize, 32); + let mem32 = self.mem[pos..pos + 32].to_vec(); + self.push_arbitrary(&mem32); + } fn mstore(&mut self) { let pos = u256_to_u64(self.pop()); let val = self.pop(); @@ -262,6 +300,24 @@ impl Stack { self.mem[pos as usize..].copy_from_slice(&val); } + fn jump(&mut self) { + // TODO that jump destination is valid + self.pc = u256_to_u64(self.pop()) as usize; + } + fn jump_i(&mut self) { + let new_pc = u256_to_u64(self.pop()) as usize; + if self.stack.len() > 0 { + let cond = u256_to_u64(self.pop()) as usize; + if cond != 0 { + self.pc = new_pc; + } + } + // let cont = self.pop(); + // if cont {} // TODO depends on having impl Err in pop() + } + fn jump_dest(&mut self) { + // TODO + } } fn u256_to_u64(a: [u8; 32]) -> u64 { @@ -282,6 +338,7 @@ struct Opcode { ins: u32, outs: u32, gas: u64, + // operation: fn(), } fn new_opcode(name: &str, ins: u32, outs: u32, gas: u64) -> Opcode { @@ -465,4 +522,57 @@ mod tests { assert_eq!(s.pc, 7); assert_eq!(s.pop(), str_to_u256("9")); } + + // storage and execution + #[test] + fn execute_opcodes_4() { + // contains loops + let code = hex::decode("6000356000525b600160005103600052600051600657").unwrap(); + let calldata = + hex::decode("0000000000000000000000000000000000000000000000000000000000000005") + .unwrap(); + + let mut s = Stack::new(); + s.execute(&code, &calldata, false); + + assert_eq!(s.gas, 9999999795); + assert_eq!(s.pc, 22); + assert_eq!(s.stack.len(), 0); + } + #[test] + fn execute_opcodes_5() { + // contains loops, without using mem + let code = hex::decode("6000355b6001900380600357").unwrap(); + let calldata = + hex::decode("0000000000000000000000000000000000000000000000000000000000000001") + .unwrap(); + + let mut s = Stack::new(); + s.execute(&code, &calldata, false); + + assert_eq!(s.gas, 9999999968); + assert_eq!(s.pc, 12); + + let code = hex::decode("6000355b6001900380600357").unwrap(); + let calldata = + hex::decode("0000000000000000000000000000000000000000000000000000000000000002") + .unwrap(); + + let mut s = Stack::new(); + s.execute(&code, &calldata, false); + + assert_eq!(s.gas, 9999999942); + assert_eq!(s.pc, 12); + + let code = hex::decode("6000355b6001900380600357").unwrap(); + let calldata = + hex::decode("0000000000000000000000000000000000000000000000000000000000000005") + .unwrap(); + + let mut s = Stack::new(); + s.execute(&code, &calldata, false); + + assert_eq!(s.gas, 9999999864); + assert_eq!(s.pc, 12); + } }