use crate::{
constraints::reg_key::{
GetRegMut,
ProgramRegistersSegment,
SystemRegisters,
split_registers,
},
error::IoResult,
interpreter::{
EcalHandler,
ExecutableTransaction,
Interpreter,
Memory,
alu,
executors::instruction::{
Execute,
checked_nth_root,
},
flow::{
JumpArgs,
JumpMode,
},
internal::inc_pc,
storage::key_range,
},
prelude::*,
state::ExecuteState,
verification::Verifier,
};
use core::ops::Div;
use fuel_asm::{
Instruction,
PanicReason,
RegId,
narrowint,
wideint,
};
use fuel_tx::Bytes32;
use fuel_types::Word;
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::ADD
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().add())?;
let (a, b, c) = self.unpack();
interpreter.alu_capture_overflow(
a,
u128::overflowing_add,
interpreter.registers[b].into(),
interpreter.registers[c].into(),
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::ADDI
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().addi())?;
let (a, b, imm) = self.unpack();
interpreter.alu_capture_overflow(
a,
u128::overflowing_add,
interpreter.registers[b].into(),
imm.into(),
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::AND
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().and())?;
let (a, b, c) = self.unpack();
interpreter.alu_set(a, interpreter.registers[b] & interpreter.registers[c])?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::ANDI
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().andi())?;
let (a, b, imm) = self.unpack();
interpreter.alu_set(a, interpreter.registers[b] & Word::from(imm))?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::DIV
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().div())?;
let (a, b, c) = self.unpack();
let c = interpreter.registers[c];
interpreter.alu_error(a, Word::div, interpreter.registers[b], c, c == 0)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::DIVI
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().divi())?;
let (a, b, imm) = self.unpack();
let imm = Word::from(imm);
interpreter.alu_error(a, Word::div, interpreter.registers[b], imm, imm == 0)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::EQ
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().eq_())?;
let (a, b, c) = self.unpack();
interpreter.alu_set(
a,
(interpreter.registers[b] == interpreter.registers[c]) as Word,
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::EXP
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().exp())?;
let (a, b, c) = self.unpack();
interpreter.alu_boolean_overflow(
a,
alu::exp,
interpreter.registers[b],
interpreter.registers[c],
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::EXPI
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().expi())?;
let (a, b, imm) = self.unpack();
let expo = u32::from(imm);
interpreter.alu_boolean_overflow(
a,
Word::overflowing_pow,
interpreter.registers[b],
expo,
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::GT
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().gt())?;
let (a, b, c) = self.unpack();
interpreter.alu_set(
a,
(interpreter.registers[b] > interpreter.registers[c]) as Word,
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::LT
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().lt())?;
let (a, b, c) = self.unpack();
interpreter.alu_set(
a,
(interpreter.registers[b] < interpreter.registers[c]) as Word,
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::WDCM
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().wdcm())?;
let (a, b, c, imm) = self.unpack();
let args = wideint::CompareArgs::from_imm(imm)
.ok_or(PanicReason::InvalidImmediateValue)?;
interpreter.alu_wideint_cmp_u128(
a,
interpreter.registers[b],
interpreter.registers[c],
args,
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::WQCM
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().wqcm())?;
let (a, b, c, imm) = self.unpack();
let args = wideint::CompareArgs::from_imm(imm)
.ok_or(PanicReason::InvalidImmediateValue)?;
interpreter.alu_wideint_cmp_u256(
a,
interpreter.registers[b],
interpreter.registers[c],
args,
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::WDOP
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().wdop())?;
let (a, b, c, imm) = self.unpack();
let args =
wideint::MathArgs::from_imm(imm).ok_or(PanicReason::InvalidImmediateValue)?;
interpreter.alu_wideint_op_u128(
interpreter.registers[a],
interpreter.registers[b],
interpreter.registers[c],
args,
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::WQOP
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().wqop())?;
let (a, b, c, imm) = self.unpack();
let args =
wideint::MathArgs::from_imm(imm).ok_or(PanicReason::InvalidImmediateValue)?;
interpreter.alu_wideint_op_u256(
interpreter.registers[a],
interpreter.registers[b],
interpreter.registers[c],
args,
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::WDML
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().wdml())?;
let (a, b, c, imm) = self.unpack();
let args =
wideint::MulArgs::from_imm(imm).ok_or(PanicReason::InvalidImmediateValue)?;
interpreter.alu_wideint_mul_u128(
interpreter.registers[a],
interpreter.registers[b],
interpreter.registers[c],
args,
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::WQML
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().wqml())?;
let (a, b, c, imm) = self.unpack();
let args =
wideint::MulArgs::from_imm(imm).ok_or(PanicReason::InvalidImmediateValue)?;
interpreter.alu_wideint_mul_u256(
interpreter.registers[a],
interpreter.registers[b],
interpreter.registers[c],
args,
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::WDDV
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().wddv())?;
let (a, b, c, imm) = self.unpack();
let args =
wideint::DivArgs::from_imm(imm).ok_or(PanicReason::InvalidImmediateValue)?;
interpreter.alu_wideint_div_u128(
interpreter.registers[a],
interpreter.registers[b],
interpreter.registers[c],
args,
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::WQDV
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().wqdv())?;
let (a, b, c, imm) = self.unpack();
let args =
wideint::DivArgs::from_imm(imm).ok_or(PanicReason::InvalidImmediateValue)?;
interpreter.alu_wideint_div_u256(
interpreter.registers[a],
interpreter.registers[b],
interpreter.registers[c],
args,
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::WDMD
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().wdmd())?;
let (a, b, c, d) = self.unpack();
interpreter.alu_wideint_muldiv_u128(
interpreter.registers[a],
interpreter.registers[b],
interpreter.registers[c],
interpreter.registers[d],
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::WQMD
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().wqmd())?;
let (a, b, c, d) = self.unpack();
interpreter.alu_wideint_muldiv_u256(
interpreter.registers[a],
interpreter.registers[b],
interpreter.registers[c],
interpreter.registers[d],
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::WDAM
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().wdam())?;
let (a, b, c, d) = self.unpack();
interpreter.alu_wideint_addmod_u128(
interpreter.registers[a],
interpreter.registers[b],
interpreter.registers[c],
interpreter.registers[d],
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::WQAM
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().wqam())?;
let (a, b, c, d) = self.unpack();
interpreter.alu_wideint_addmod_u256(
interpreter.registers[a],
interpreter.registers[b],
interpreter.registers[c],
interpreter.registers[d],
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::WDMM
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().wdmm())?;
let (a, b, c, d) = self.unpack();
interpreter.alu_wideint_mulmod_u128(
interpreter.registers[a],
interpreter.registers[b],
interpreter.registers[c],
interpreter.registers[d],
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::WQMM
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().wqmm())?;
let (a, b, c, d) = self.unpack();
interpreter.alu_wideint_mulmod_u256(
interpreter.registers[a],
interpreter.registers[b],
interpreter.registers[c],
interpreter.registers[d],
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::MLOG
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().mlog())?;
let (a, b, c) = self.unpack();
let (lhs, rhs) = (interpreter.registers[b], interpreter.registers[c]);
interpreter.alu_error(
a,
|l, r| {
l.checked_ilog(r)
.expect("checked_ilog returned None for valid values")
as Word
},
lhs,
rhs,
lhs == 0 || rhs <= 1,
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::MOD
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().mod_op())?;
let (a, b, c) = self.unpack();
let rhs = interpreter.registers[c];
interpreter.alu_error(
a,
Word::wrapping_rem,
interpreter.registers[b],
rhs,
rhs == 0,
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::MODI
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().modi())?;
let (a, b, imm) = self.unpack();
let rhs = Word::from(imm);
interpreter.alu_error(
a,
Word::wrapping_rem,
interpreter.registers[b],
rhs,
rhs == 0,
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::MOVE
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().move_op())?;
let (a, b) = self.unpack();
interpreter.alu_set(a, interpreter.registers[b])?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::MOVI
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().movi())?;
let (a, imm) = self.unpack();
interpreter.alu_set(a, Word::from(imm))?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::MROO
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().mroo())?;
let (a, b, c) = self.unpack();
let (lhs, rhs) = (interpreter.registers[b], interpreter.registers[c]);
interpreter.alu_error(
a,
|l, r| {
checked_nth_root(l, r)
.expect("checked_nth_root returned None for valid values")
as Word
},
lhs,
rhs,
rhs == 0,
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::MUL
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().mul())?;
let (a, b, c) = self.unpack();
interpreter.alu_capture_overflow(
a,
u128::overflowing_mul,
interpreter.registers[b].into(),
interpreter.registers[c].into(),
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::MULI
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().muli())?;
let (a, b, imm) = self.unpack();
interpreter.alu_capture_overflow(
a,
u128::overflowing_mul,
interpreter.registers[b].into(),
imm.into(),
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::MLDV
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().mldv())?;
let (a, b, c, d) = self.unpack();
interpreter.alu_muldiv(
a,
interpreter.registers[b],
interpreter.registers[c],
interpreter.registers[d],
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::NIOP
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter
.gas_charge(interpreter.gas_costs().niop().map_err(PanicReason::from)?)?;
let (a, b, c, imm) = self.unpack();
let args = narrowint::MathArgs::from_imm(imm)
.ok_or(PanicReason::InvalidImmediateValue)?;
interpreter.alu_narrowint_op(
a,
interpreter.registers[b],
interpreter.registers[c],
args,
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::NOOP
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().noop())?;
interpreter.alu_clear()?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::NOT
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().not())?;
let (a, b) = self.unpack();
interpreter.alu_set(a, !interpreter.registers[b])?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::OR
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().or())?;
let (a, b, c) = self.unpack();
interpreter.alu_set(a, interpreter.registers[b] | interpreter.registers[c])?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::ORI
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().ori())?;
let (a, b, imm) = self.unpack();
interpreter.alu_set(a, interpreter.registers[b] | Word::from(imm))?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::SLL
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().sll())?;
let (a, b, c) = self.unpack();
interpreter.alu_set(
a,
if let Ok(c) = interpreter.registers[c].try_into() {
Word::checked_shl(interpreter.registers[b], c).unwrap_or_default()
} else {
0
},
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::SLLI
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().slli())?;
let (a, b, imm) = self.unpack();
let rhs = u32::from(imm);
interpreter.alu_set(
a,
interpreter.registers[b]
.checked_shl(rhs)
.unwrap_or_default(),
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::SRL
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().srl())?;
let (a, b, c) = self.unpack();
interpreter.alu_set(
a,
if let Ok(c) = interpreter.registers[c].try_into() {
Word::checked_shr(interpreter.registers[b], c).unwrap_or_default()
} else {
0
},
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::SRLI
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().srli())?;
let (a, b, imm) = self.unpack();
let rhs = u32::from(imm);
interpreter.alu_set(
a,
interpreter.registers[b]
.checked_shr(rhs)
.unwrap_or_default(),
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::SUB
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().sub())?;
let (a, b, c) = self.unpack();
interpreter.alu_capture_overflow(
a,
u128::overflowing_sub,
interpreter.registers[b].into(),
interpreter.registers[c].into(),
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::SUBI
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().subi())?;
let (a, b, imm) = self.unpack();
interpreter.alu_capture_overflow(
a,
u128::overflowing_sub,
interpreter.registers[b].into(),
imm.into(),
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::XOR
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().xor())?;
let (a, b, c) = self.unpack();
interpreter.alu_set(a, interpreter.registers[b] ^ interpreter.registers[c])?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::XORI
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().xori())?;
let (a, b, imm) = self.unpack();
interpreter.alu_set(a, interpreter.registers[b] ^ Word::from(imm))?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::JI
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().ji())?;
let imm = self.unpack();
interpreter.jump(JumpArgs::new(JumpMode::RelativeIS).to_address(imm.into()))?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::JNEI
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().jnei())?;
let (a, b, imm) = self.unpack();
interpreter.jump(
JumpArgs::new(JumpMode::RelativeIS)
.with_condition(interpreter.registers[a] != interpreter.registers[b])
.to_address(imm.into()),
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::JNZI
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().jnzi())?;
let (a, imm) = self.unpack();
interpreter.jump(
JumpArgs::new(JumpMode::RelativeIS)
.with_condition(interpreter.registers[a] != 0)
.to_address(imm.into()),
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::JMP
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().jmp())?;
let a = self.unpack();
interpreter.jump(
JumpArgs::new(JumpMode::RelativeIS).to_address(interpreter.registers[a]),
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::JNE
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().jne())?;
let (a, b, c) = self.unpack();
interpreter.jump(
JumpArgs::new(JumpMode::RelativeIS)
.with_condition(interpreter.registers[a] != interpreter.registers[b])
.to_address(interpreter.registers[c]),
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::JMPF
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().jmpf())?;
let (a, offset) = self.unpack();
interpreter.jump(
JumpArgs::new(JumpMode::RelativeForwards)
.to_address(interpreter.registers[a])
.plus_fixed(offset.into()),
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::JMPB
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().jmpb())?;
let (a, offset) = self.unpack();
interpreter.jump(
JumpArgs::new(JumpMode::RelativeBackwards)
.to_address(interpreter.registers[a])
.plus_fixed(offset.into()),
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::JNZF
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().jnzf())?;
let (a, b, offset) = self.unpack();
interpreter.jump(
JumpArgs::new(JumpMode::RelativeForwards)
.with_condition(interpreter.registers[a] != 0)
.to_address(interpreter.registers[b])
.plus_fixed(offset.into()),
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::JNZB
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().jnzb())?;
let (a, b, offset) = self.unpack();
interpreter.jump(
JumpArgs::new(JumpMode::RelativeBackwards)
.with_condition(interpreter.registers[a] != 0)
.to_address(interpreter.registers[b])
.plus_fixed(offset.into()),
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::JNEF
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().jnef())?;
let (a, b, c, offset) = self.unpack();
interpreter.jump(
JumpArgs::new(JumpMode::RelativeForwards)
.with_condition(interpreter.registers[a] != interpreter.registers[b])
.to_address(interpreter.registers[c])
.plus_fixed(offset.into()),
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::JNEB
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().jneb())?;
let (a, b, c, offset) = self.unpack();
interpreter.jump(
JumpArgs::new(JumpMode::RelativeBackwards)
.with_condition(interpreter.registers[a] != interpreter.registers[b])
.to_address(interpreter.registers[c])
.plus_fixed(offset.into()),
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::JAL
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().jmp())?;
let (reg_ret_addr, reg_target, offset) = self.unpack();
let ret_addr =
interpreter.registers[RegId::PC].saturating_add(Instruction::SIZE as u64);
interpreter.write_user_register(reg_ret_addr, ret_addr)?;
interpreter.jump(
JumpArgs::new(JumpMode::Assign)
.to_address(interpreter.registers[reg_target])
.plus_fixed(offset.into()),
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::RET
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().ret())?;
let a = self.unpack();
let ra = interpreter.registers[a];
interpreter.ret(ra)?;
Ok(ExecuteState::Return(ra))
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::RETD
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
let (a, b) = self.unpack();
let len = interpreter.registers[b];
interpreter.dependent_gas_charge(interpreter.gas_costs().retd(), len)?;
Ok(interpreter
.ret_data(interpreter.registers[a], len)
.map(ExecuteState::ReturnData)?)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::RVRT
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().rvrt())?;
let a = self.unpack();
let ra = interpreter.registers[a];
interpreter.revert(ra)?;
Ok(ExecuteState::Revert(ra))
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::SMO
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
let (a, b, c, d) = self.unpack();
interpreter.dependent_gas_charge(
interpreter.gas_costs().smo(),
interpreter.registers[c],
)?;
interpreter.message_output(
interpreter.registers[a],
interpreter.registers[b],
interpreter.registers[c],
interpreter.registers[d],
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::ALOC
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
let a = self.unpack();
let number_of_bytes = interpreter.registers[a];
interpreter
.dependent_gas_charge(interpreter.gas_costs().aloc(), number_of_bytes)?;
interpreter.malloc(number_of_bytes)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::CFEI
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
let number_of_bytes = self.unpack().into();
interpreter
.dependent_gas_charge(interpreter.gas_costs().cfei(), number_of_bytes)?;
interpreter.stack_pointer_overflow(Word::overflowing_add, number_of_bytes)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::CFE
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
let a = self.unpack();
let number_of_bytes = interpreter.registers[a];
interpreter
.dependent_gas_charge(interpreter.gas_costs().cfe(), number_of_bytes)?;
interpreter.stack_pointer_overflow(Word::overflowing_add, number_of_bytes)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::CFSI
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().cfsi())?;
let imm = self.unpack();
interpreter.stack_pointer_overflow(Word::overflowing_sub, imm.into())?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::CFS
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().cfsi())?;
let a = self.unpack();
interpreter
.stack_pointer_overflow(Word::overflowing_sub, interpreter.registers[a])?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::PSHL
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().pshl())?;
let bitmask = self.unpack();
interpreter.push_selected_registers(ProgramRegistersSegment::Low, bitmask)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::PSHH
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().pshh())?;
let bitmask = self.unpack();
interpreter.push_selected_registers(ProgramRegistersSegment::High, bitmask)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::POPL
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().popl())?;
let bitmask = self.unpack();
interpreter.pop_selected_registers(ProgramRegistersSegment::Low, bitmask)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::POPH
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().poph())?;
let bitmask = self.unpack();
interpreter.pop_selected_registers(ProgramRegistersSegment::High, bitmask)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::LB
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().lb())?;
let (a, b, imm) = self.unpack();
interpreter.load_u8(a, interpreter.registers[b], imm)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::LQW
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().lw())?;
let (a, b, imm) = self.unpack();
interpreter.load_u16(a, interpreter.registers[b], imm)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::LHW
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().lw())?;
let (a, b, imm) = self.unpack();
interpreter.load_u32(a, interpreter.registers[b], imm)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::LW
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().lw())?;
let (a, b, imm) = self.unpack();
interpreter.load_u64(a, interpreter.registers[b], imm)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::MCL
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
let (a, b) = self.unpack();
let len = interpreter.registers[b];
interpreter.dependent_gas_charge(interpreter.gas_costs().mcl(), len)?;
interpreter.memclear(interpreter.registers[a], len)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::MCLI
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
let (a, imm) = self.unpack();
let len = Word::from(imm);
interpreter.dependent_gas_charge(interpreter.gas_costs().mcli(), len)?;
interpreter.memclear(interpreter.registers[a], len)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::MCP
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
let (a, b, c) = self.unpack();
let len = interpreter.registers[c];
interpreter.dependent_gas_charge(interpreter.gas_costs().mcp(), len)?;
interpreter.memcopy(interpreter.registers[a], interpreter.registers[b], len)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::MCPI
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
let (a, b, imm) = self.unpack();
let len = imm.into();
interpreter.dependent_gas_charge(interpreter.gas_costs().mcpi(), len)?;
interpreter.memcopy(interpreter.registers[a], interpreter.registers[b], len)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::MEQ
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
let (a, b, c, d) = self.unpack();
let len = interpreter.registers[d];
interpreter.dependent_gas_charge(interpreter.gas_costs().meq(), len)?;
interpreter.memeq(a, interpreter.registers[b], interpreter.registers[c], len)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::SB
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().sb())?;
let (a, b, imm) = self.unpack();
interpreter.store_u8(interpreter.registers[a], interpreter.registers[b], imm)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::SQW
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().sw())?;
let (a, b, imm) = self.unpack();
interpreter.store_u16(interpreter.registers[a], interpreter.registers[b], imm)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::SHW
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().sw())?;
let (a, b, imm) = self.unpack();
interpreter.store_u32(interpreter.registers[a], interpreter.registers[b], imm)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::SW
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().sw())?;
let (a, b, imm) = self.unpack();
interpreter.store_u64(interpreter.registers[a], interpreter.registers[b], imm)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::BAL
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().bal())?;
let (a, b, c) = self.unpack();
interpreter.contract_balance(
a,
interpreter.registers[b],
interpreter.registers[c],
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::BHEI
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().bhei())?;
let a = self.unpack();
interpreter.block_height(a)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::BHSH
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().bhsh())?;
let (a, b) = self.unpack();
interpreter.block_hash(interpreter.registers[a], interpreter.registers[b])?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::BURN
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().burn())?;
let (a, b) = self.unpack();
interpreter.burn(interpreter.registers[a], interpreter.registers[b])?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::CALL
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
let (a, b, c, d) = self.unpack();
interpreter.prepare_call(a, b, c, d)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::CB
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().cb())?;
let a = self.unpack();
interpreter.block_proposer(interpreter.registers[a])?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::CCP
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
let (a, b, c, d) = self.unpack();
interpreter.code_copy(
interpreter.registers[a],
interpreter.registers[b],
interpreter.registers[c],
interpreter.registers[d],
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::CROO
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
let (a, b) = self.unpack();
interpreter.code_root(interpreter.registers[a], interpreter.registers[b])?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::CSIZ
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
let (a, b) = self.unpack();
interpreter.code_size(a, interpreter.registers[b])?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::LDC
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
let (a, b, c, mode) = self.unpack();
interpreter.load_contract_code(
interpreter.registers[a],
interpreter.registers[b],
interpreter.registers[c],
mode,
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::LOG
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().log())?;
let (a, b, c, d) = self.unpack();
interpreter.log(
interpreter.registers[a],
interpreter.registers[b],
interpreter.registers[c],
interpreter.registers[d],
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::LOGD
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
let (a, b, c, d) = self.unpack();
interpreter.dependent_gas_charge(
interpreter.gas_costs().logd(),
interpreter.registers[d],
)?;
interpreter.log_data(
interpreter.registers[a],
interpreter.registers[b],
interpreter.registers[c],
interpreter.registers[d],
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::MINT
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().mint())?;
let (a, b) = self.unpack();
interpreter.mint(interpreter.registers[a], interpreter.registers[b])?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::SCWQ
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().noop())?;
let (a, b, c) = self.unpack();
let key =
Bytes32::new(interpreter.memory().read_bytes(interpreter.registers[a])?);
let range = crate::convert::to_usize(interpreter.registers[c])
.ok_or(PanicReason::TooManySlots)?;
let contract_id = interpreter.internal_contract()?;
let mut all_previously_set = true;
for key in key_range(key, range) {
let key = key.ok_or(PanicReason::TooManySlots)?;
let was_set =
interpreter.storage_read_slot(contract_id, key, |_, v| v.is_some())?;
if !was_set {
all_previously_set = false;
}
}
interpreter.write_user_register_legacy(b, all_previously_set.into())?;
interpreter.storage_clear_slot_range(contract_id, key, range)?;
inc_pc(interpreter.registers.pc_mut());
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::SRW
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().noop())?;
let (a, b, c, d) = self.unpack();
let key =
Bytes32::new(interpreter.memory().read_bytes(interpreter.registers[c])?);
let offset = d.to_u8() as usize;
let contract_id = interpreter.internal_contract()?;
if a == b {
return Err(RuntimeError::Recoverable(
PanicReason::ReservedRegisterNotWritable,
));
}
let result =
interpreter.storage_read_slot(contract_id, key, |_, v| match v {
Some(bytes) => {
let offset_bytes = offset.saturating_mul(8);
let end_bytes = offset_bytes.saturating_add(8);
if (bytes.len() as u64) < (end_bytes as u64) {
return Err(PanicReason::StorageOutOfBounds);
}
let mut buf = [0u8; 8];
buf.copy_from_slice(&bytes[offset_bytes..end_bytes]);
Ok(Some(Word::from_be_bytes(buf)))
}
None => Ok(None),
})??;
if let Some(value) = result {
interpreter.write_user_register_legacy(a, value)?;
interpreter.write_user_register_legacy(b, 1)?;
} else {
interpreter.write_user_register_legacy(a, 0)?;
interpreter.write_user_register_legacy(b, 0)?;
}
inc_pc(interpreter.registers.pc_mut());
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::SRWQ
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().noop())?;
let (a, b, c, d) = self.unpack();
let start_ptr = interpreter.registers[a];
let key =
Bytes32::new(interpreter.memory().read_bytes(interpreter.registers[c])?);
let range = crate::convert::to_usize(interpreter.registers[d])
.ok_or(PanicReason::TooManySlots)?;
let contract_id = interpreter.internal_contract()?;
let owner = interpreter.ownership_registers();
let mut all_previously_set = true;
for (i, key) in key_range(key, range).enumerate() {
let key = key.ok_or(PanicReason::TooManySlots)?;
interpreter.storage_read_slot(contract_id, key, |memory, v| {
let dst_ptr = start_ptr.saturating_add((i as u64).saturating_mul(32));
let dst = memory.write(owner, dst_ptr, 32u64)?;
match v {
Some(bytes) => {
if bytes.len() != Bytes32::LEN {
return Err(PanicReason::StorageOutOfBounds);
}
dst.copy_from_slice(bytes.as_ref().as_ref());
Ok(())
}
None => {
all_previously_set = false;
dst.fill(0);
Ok(())
}
}
})??;
}
interpreter.write_user_register_legacy(b, all_previously_set.into())?;
inc_pc(interpreter.registers.pc_mut());
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::SWW
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().noop())?;
let (a, b, c) = self.unpack();
let key =
Bytes32::new(interpreter.memory().read_bytes(interpreter.registers[a])?);
let contract_id = interpreter.internal_contract()?;
let mut value = Bytes32::zeroed();
value.as_mut()[..8].copy_from_slice(&interpreter.registers[c].to_be_bytes());
let created_new =
interpreter.storage_read_slot(contract_id, key, |_, v| v.is_none())?;
interpreter.storage_write_slot(contract_id, key, value.to_vec())?;
interpreter.write_user_register_legacy(b, created_new.into())?;
inc_pc(interpreter.registers.pc_mut());
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::SWWQ
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().noop())?;
let (a, b, c, d) = self.unpack();
let key =
Bytes32::new(interpreter.memory().read_bytes(interpreter.registers[a])?);
let start_ptr = interpreter.registers[c];
let range = crate::convert::to_usize(interpreter.registers[d])
.ok_or(PanicReason::TooManySlots)?;
let contract_id = interpreter.internal_contract()?;
let mut num_previously_unset = 0u64;
for (i, key) in key_range(key, range).enumerate() {
let key = key.ok_or(PanicReason::TooManySlots)?;
let previously_set =
interpreter.storage_read_slot(contract_id, key, |_, v| v.is_some())?;
#[allow(clippy::arithmetic_side_effects)] if !previously_set {
num_previously_unset += 1;
}
interpreter.storage_write_slot_from_memory(contract_id, key, |memory| {
let src_ptr = start_ptr.saturating_add((i as u64).saturating_mul(32));
Ok(memory.read(src_ptr, 32u64)?)
})?;
}
interpreter.write_user_register_legacy(b, num_previously_unset)?;
inc_pc(interpreter.registers.pc_mut());
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::TIME
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().time())?;
let (a, b) = self.unpack();
interpreter.timestamp(a, interpreter.registers[b])?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::ECK1
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().eck1())?;
let (a, b, c) = self.unpack();
interpreter.secp256k1_recover(
interpreter.registers[a],
interpreter.registers[b],
interpreter.registers[c],
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::ECR1
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().ecr1())?;
let (a, b, c) = self.unpack();
interpreter.secp256r1_recover(
interpreter.registers[a],
interpreter.registers[b],
interpreter.registers[c],
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::ED19
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
let (a, b, c, len) = self.unpack();
let mut len = interpreter.registers[len];
if len == 0 {
len = 32;
}
interpreter.dependent_gas_charge(interpreter.gas_costs().ed19(), len)?;
interpreter.ed25519_verify(
interpreter.registers[a],
interpreter.registers[b],
interpreter.registers[c],
len,
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::K256
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
let (a, b, c) = self.unpack();
let len = interpreter.registers[c];
interpreter.dependent_gas_charge(interpreter.gas_costs().k256(), len)?;
interpreter.keccak256(interpreter.registers[a], interpreter.registers[b], len)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::S256
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
let (a, b, c) = self.unpack();
let len = interpreter.registers[c];
interpreter.dependent_gas_charge(interpreter.gas_costs().s256(), len)?;
interpreter.sha256(interpreter.registers[a], interpreter.registers[b], len)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::FLAG
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().flag())?;
let a = self.unpack();
interpreter.set_flag(interpreter.registers[a])?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::GM
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().gm())?;
let (a, imm) = self.unpack();
interpreter.metadata(a, imm.into())?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::GTF
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().gtf())?;
let (a, b, imm) = self.unpack();
interpreter.get_transaction_field(a, interpreter.registers[b], imm.into())?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::TR
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().tr())?;
let (a, b, c) = self.unpack();
interpreter.transfer(
interpreter.registers[a],
interpreter.registers[b],
interpreter.registers[c],
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::TRO
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().tro())?;
let (a, b, c, d) = self.unpack();
interpreter.transfer_output(
interpreter.registers[a],
interpreter.registers[b],
interpreter.registers[c],
interpreter.registers[d],
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::ECAL
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
let (a, b, c, d) = self.unpack();
interpreter.external_call(a, b, c, d)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::BSIZ
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
let (a, b) = self.unpack();
interpreter.blob_size(a, interpreter.registers[b])?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::BLDD
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
let (a, b, c, d) = self.unpack();
interpreter.blob_load_data(
interpreter.registers[a],
interpreter.registers[b],
interpreter.registers[c],
interpreter.registers[d],
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::ECOP
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter
.gas_charge(interpreter.gas_costs().ecop().map_err(PanicReason::from)?)?;
let (a, b, c, d) = self.unpack();
interpreter.ec_operation(
interpreter.registers[a],
interpreter.registers[b],
interpreter.registers[c],
interpreter.registers[d],
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::EPAR
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
let (a, b, c, d) = self.unpack();
let len = interpreter.registers[c];
interpreter.dependent_gas_charge(
interpreter.gas_costs().epar().map_err(PanicReason::from)?,
len,
)?;
interpreter.ec_pairing(
a,
interpreter.registers[b],
len,
interpreter.registers[d],
)?;
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::SCLR
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().noop())?;
let (r_key_ptr, r_num_slots) = self.unpack();
let start_key = Bytes32::from(
interpreter
.memory()
.read_bytes(interpreter.registers[r_key_ptr])?,
);
let num_slots = crate::convert::to_usize(interpreter.registers[r_num_slots])
.ok_or(PanicReason::TooManySlots)?;
let contract_id = interpreter.internal_contract()?;
interpreter.storage_clear_slot_range(contract_id, start_key, num_slots)?;
let (SystemRegisters { pc, .. }, _) = split_registers(&mut interpreter.registers);
inc_pc(pc);
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::SRDD
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().noop())?;
let (r_buffer_ptr, r_key_ptr, r_offset, r_len) = self.unpack();
interpreter.dynamic_storage_read(
interpreter.registers[r_buffer_ptr],
interpreter.registers[r_key_ptr],
interpreter.registers[r_offset],
interpreter.registers[r_len],
)?;
let (SystemRegisters { pc, .. }, _) = split_registers(&mut interpreter.registers);
inc_pc(pc);
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::SRDI
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().noop())?;
let (r_buffer_ptr, r_key_ptr, r_offset, imm_len) = self.unpack();
interpreter.dynamic_storage_read(
interpreter.registers[r_buffer_ptr],
interpreter.registers[r_key_ptr],
interpreter.registers[r_offset],
imm_len.to_u8().into(),
)?;
let (SystemRegisters { pc, .. }, _) = split_registers(&mut interpreter.registers);
inc_pc(pc);
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::SWRD
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().noop())?;
let (r_key_ptr, r_value_ptr, r_len) = self.unpack();
interpreter.dynamic_storage_write(
interpreter.registers[r_key_ptr],
interpreter.registers[r_value_ptr],
interpreter.registers[r_len],
)?;
let (SystemRegisters { pc, .. }, _) = split_registers(&mut interpreter.registers);
inc_pc(pc);
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::SWRI
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().noop())?;
let (r_key_ptr, r_value_ptr, imm_len) = self.unpack();
interpreter.dynamic_storage_write(
interpreter.registers[r_key_ptr],
interpreter.registers[r_value_ptr],
imm_len.to_u16().into(),
)?;
let (SystemRegisters { pc, .. }, _) = split_registers(&mut interpreter.registers);
inc_pc(pc);
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::SUPD
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().noop())?;
let (r_key_ptr, r_value_ptr, r_offset, r_len) = self.unpack();
interpreter.dynamic_storage_update(
interpreter.registers[r_key_ptr],
interpreter.registers[r_value_ptr],
interpreter.registers[r_offset],
interpreter.registers[r_len],
)?;
let (SystemRegisters { pc, .. }, _) = split_registers(&mut interpreter.registers);
inc_pc(pc);
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::SUPI
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().noop())?;
let (r_key_ptr, r_value_ptr, r_offset, imm_len) = self.unpack();
interpreter.dynamic_storage_update(
interpreter.registers[r_key_ptr],
interpreter.registers[r_value_ptr],
interpreter.registers[r_offset],
imm_len.to_u8().into(),
)?;
let (SystemRegisters { pc, .. }, _) = split_registers(&mut interpreter.registers);
inc_pc(pc);
Ok(ExecuteState::Proceed)
}
}
impl<M, S, Tx, Ecal, V> Execute<M, S, Tx, Ecal, V> for fuel_asm::op::SPLD
where
M: Memory,
S: InterpreterStorage,
Tx: ExecutableTransaction,
Ecal: EcalHandler,
V: Verifier,
{
fn execute(
self,
interpreter: &mut Interpreter<M, S, Tx, Ecal, V>,
) -> IoResult<ExecuteState, S::DataError> {
interpreter.gas_charge(interpreter.gas_costs().noop())?;
let (r_dst_len, r_key_ptr) = self.unpack();
let key = Bytes32::from(
interpreter
.memory()
.read_bytes(interpreter.registers[r_key_ptr])?,
);
interpreter.storage_preload(r_dst_len, key)?;
let (SystemRegisters { pc, .. }, _) = split_registers(&mut interpreter.registers);
inc_pc(pc);
Ok(ExecuteState::Proceed)
}
}