use crate::{
Error, U256,
vm::{
Ext,
evm::{EVMGas, Interpreter, interpreter::Halt, util::as_usize_or_halt},
},
};
use core::{cmp::max, ops::ControlFlow};
use revm::interpreter::gas::{BASE, VERYLOW, copy_cost_verylow};
pub fn mload<E: Ext>(interpreter: &mut Interpreter<E>) -> ControlFlow<Halt> {
interpreter.ext.charge_or_halt(EVMGas(VERYLOW))?;
let ([], top) = interpreter.stack.popn_top()?;
let offset = as_usize_or_halt::<E::T>(*top)?;
interpreter.memory.resize(offset, 32)?;
*top = U256::from_big_endian(interpreter.memory.slice_len(offset, 32));
ControlFlow::Continue(())
}
pub fn mstore<E: Ext>(interpreter: &mut Interpreter<E>) -> ControlFlow<Halt> {
interpreter.ext.charge_or_halt(EVMGas(VERYLOW))?;
let [offset, value] = interpreter.stack.popn()?;
let offset = as_usize_or_halt::<E::T>(offset)?;
interpreter.memory.resize(offset, 32)?;
interpreter.memory.set(offset, &value.to_big_endian());
ControlFlow::Continue(())
}
pub fn mstore8<E: Ext>(interpreter: &mut Interpreter<E>) -> ControlFlow<Halt> {
interpreter.ext.charge_or_halt(EVMGas(VERYLOW))?;
let [offset, value] = interpreter.stack.popn()?;
let offset = as_usize_or_halt::<E::T>(offset)?;
interpreter.memory.resize(offset, 1)?;
interpreter.memory.set(offset, &[value.byte(0)]);
ControlFlow::Continue(())
}
pub fn msize<E: Ext>(interpreter: &mut Interpreter<E>) -> ControlFlow<Halt> {
interpreter.ext.charge_or_halt(EVMGas(BASE))?;
interpreter.stack.push(U256::from(interpreter.memory.size()))
}
pub fn mcopy<E: Ext>(interpreter: &mut Interpreter<E>) -> ControlFlow<Halt> {
let [dst, src, len] = interpreter.stack.popn()?;
let len = as_usize_or_halt::<E::T>(len)?;
let Some(gas_cost) = copy_cost_verylow(len) else {
return ControlFlow::Break(Error::<E::T>::OutOfGas.into());
};
interpreter.ext.charge_or_halt(EVMGas(gas_cost))?;
if len == 0 {
return ControlFlow::Continue(());
}
let dst = as_usize_or_halt::<E::T>(dst)?;
let src = as_usize_or_halt::<E::T>(src)?;
interpreter.memory.resize(max(dst, src), len)?;
interpreter.memory.copy(dst, src, len);
ControlFlow::Continue(())
}