yevm-core 0.1.0

Async, WASM-native Ethereum VM engine: opcode dispatch, gas accounting, precompiles, state traits, structured trace events.
Documentation
use crate::{
    Call,
    evm::{self, Context, Evm, EvmResult, EvmYield, HaltReason},
    state::State,
};

const LOG0: u8 = 0xA0;

pub fn log<S: State>(evm: &mut Evm, ctx: &Context, _: &Call, state: &mut S) -> EvmResult<()> {
    if ctx.is_static {
        return Err(EvmYield::Halt(HaltReason::NonStatic));
    }
    let n: usize = (evm.code[evm.pc] - LOG0) as usize;
    let total = 2 + n;
    if evm.stack.len() < total {
        return Err(EvmYield::Halt(HaltReason::StackUnderflow));
    }

    let [offset, size] = evm.peek()?;
    evm::mem_check_int(offset, size)?;
    let (offset, size) = (offset.as_usize(), size.as_usize());

    let base = 375 + 375 * n as i64;
    let max = (evm.gas_remaining() - base) / 8;
    if max < 0 || size > max as usize {
        evm.pending_gas_charge += evm.gas_remaining();
        return Err(EvmYield::Halt(HaltReason::OutOfGas));
    }

    let gas = base + 8 * size as i64;
    evm.gas_charge(gas)?;

    let data = evm.mem_get(offset, size)?.to_vec();

    let topics = evm.stack.iter().rev().skip(2).take(n).cloned().collect();

    evm.pending_stack_pops = total;
    state.log(data.into(), topics);
    Ok(())
}