fuel-vm 0.66.3

FuelVM interpreter.
Documentation
use alloc::{
    vec,
    vec::Vec,
};

use crate::error::PanicOrBug;

use super::*;

#[test]
fn test_return() {
    let mut frame_reg: [Word; VM_REGISTER_COUNT] = core::array::from_fn(|i| i as Word);
    frame_reg[RegId::CGAS] = 100;
    let mut expected = frame_reg;
    let frame = CallFrame::new(
        ContractId::default(),
        AssetId::default(),
        frame_reg,
        0,
        0,
        0,
    )
    .unwrap();
    let mut frames = vec![frame];
    let mut registers = [0; VM_REGISTER_COUNT];
    registers[RegId::CGAS] = 99;
    registers[RegId::GGAS] = 100;
    registers[RegId::RET] = 101;
    registers[RegId::RETL] = 102;
    registers[RegId::HP] = 1234;

    expected[RegId::CGAS] = 199;
    expected[RegId::GGAS] = 100;
    expected[RegId::RET] = 101;
    expected[RegId::RETL] = 102;
    expected[RegId::HP] = 1234;
    expected[RegId::PC] += 4;
    let mut context = Context::Call {
        block_height: Default::default(),
    };

    let mut receipts = Default::default();
    let mut memory: MemoryInstance = vec![0u8; MEM_SIZE].try_into().unwrap();
    input(
        &mut frames,
        &mut registers,
        &mut receipts,
        &mut memory,
        &mut context,
    )
    .return_from_context(Receipt::ret(Default::default(), 0, 0, 0))
    .unwrap();
    assert_eq!(registers, expected);

    input(
        &mut frames,
        &mut registers,
        &mut receipts,
        &mut memory,
        &mut context,
    )
    .ret(1)
    .unwrap();
    expected[RegId::RET] = 1;
    expected[RegId::RETL] = 0;
    expected[RegId::PC] += 4;
    assert_eq!(registers, expected);
    assert_eq!(
        *receipts.as_ref().last().unwrap(),
        Receipt::ret(
            ContractId::default(),
            1,
            expected[RegId::PC] - 4,
            expected[RegId::IS]
        )
    );

    let r = input(
        &mut frames,
        &mut registers,
        &mut receipts,
        &mut memory,
        &mut context,
    )
    .ret_data(Word::MAX, Word::MAX);
    assert_eq!(r, Err(PanicOrBug::Panic(PanicReason::MemoryOverflow)));

    let r = input(
        &mut frames,
        &mut registers,
        &mut receipts,
        &mut memory,
        &mut context,
    )
    .ret_data(VM_MAX_RAM, 1);
    assert_eq!(r, Err(PanicOrBug::Panic(PanicReason::MemoryOverflow)));

    let r = input(
        &mut frames,
        &mut registers,
        &mut receipts,
        &mut memory,
        &mut context,
    )
    .ret_data(0, VM_MAX_RAM + 1);
    assert_eq!(r, Err(PanicOrBug::Panic(PanicReason::MemoryOverflow)));

    let r = input(
        &mut frames,
        &mut registers,
        &mut receipts,
        &mut memory,
        &mut context,
    )
    .ret_data(20, 22)
    .unwrap();

    expected[RegId::RET] = 20;
    expected[RegId::RETL] = 22;
    expected[RegId::PC] += 4;
    assert_eq!(
        *input(
            &mut frames,
            &mut registers,
            &mut receipts,
            &mut memory,
            &mut context
        )
        .registers,
        expected
    );

    assert_eq!(
        *receipts.as_ref().last().unwrap(),
        Receipt::return_data_with_len(
            ContractId::default(),
            20,
            22,
            r,
            expected[RegId::PC] - 4,
            expected[RegId::IS],
            Some(vec![0u8; 22]),
        )
    );
}

fn input<'a>(
    frames: &'a mut Vec<CallFrame>,
    registers: &'a mut [Word; VM_REGISTER_COUNT],
    receipts: &'a mut ReceiptsCtx,
    memory: &'a mut MemoryInstance,
    context: &'a mut Context,
) -> RetCtx<'a> {
    RetCtx {
        frames,
        registers,
        receipts,
        memory,
        context,
        current_contract: Default::default(),
    }
}

#[test]
fn test_revert() {
    let mut receipts = Default::default();
    let pc = 10;
    let is = 20;
    revert(&mut receipts, None, Reg::new(&pc), Reg::new(&is), 99).expect("should be ok");
    assert_eq!(
        *receipts.as_ref().last().unwrap(),
        Receipt::revert(ContractId::default(), 99, pc, is)
    );
}