mirror of
https://github.com/arnaucube/evm-rs.git
synced 2026-02-02 17:06:40 +01:00
Impl mload, jump, jump_i, jump_dest, swap, dup
This commit is contained in:
110
src/lib.rs
110
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<u8> = 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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user