1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::evm::opcode::*;
use crate::evm::ConcreteStack;
use crate::evm::{Evm, Stack, Stepper};
use crate::util::w256;
// ===================================================================
// Concrete EVM
// ===================================================================
#[derive(Debug, PartialEq)]
pub enum ConcreteResult<'a> {
Continue(ConcreteEvm<'a>),
Return { data: Vec<u8> },
Revert { data: Vec<u8> },
}
pub type ConcreteEvm<'a> = Evm<'a, ConcreteStack<w256>>;
impl<'a> ConcreteEvm<'a> {
/// Execute the contract to completion.
pub fn run(mut self) -> ConcreteResult<'a> {
// Eventually, this needs a return type.
loop {
let r = self.step();
match r {
ConcreteResult::Continue(evm) => {
self = evm;
}
_ => {
return r;
}
}
}
}
}
impl<'a> Stepper for ConcreteEvm<'a> {
type Result = ConcreteResult<'a>;
/// Execute instruction at the current `pc`.
fn step(self) -> Self::Result {
let opcode = self.code[self.pc];
//
match opcode {
STOP => Self::Result::Return { data: Vec::new() },
//
ADD => {
let lhs = self.stack.peek(1);
let rhs = self.stack.peek(0);
Self::Result::Continue(self.pop(2).push(lhs + rhs).next(1))
}
PUSH1..=PUSH32 => {
// Determine push size
let n = ((opcode - PUSH1) + 1) as usize;
let pc = self.pc + 1;
// Extract bytes
let bytes = &self.code[pc..pc + n];
// Convert bytes into w256 word
let w = w256::from_be_bytes(bytes);
// Done
Self::Result::Continue(self.push(w.into()).next(n + 1))
}
//
_ => {
panic!("unknown instruction encountered");
}
}
}
}