use alloc::vec;
use crate::{
interpreter::{
InterpreterParams,
MemoryInstance,
internal::{
external_asset_id_balance_sub,
set_variable_output,
},
},
prelude::*,
};
use fuel_asm::op;
use fuel_tx::{
ConsensusParameters,
TransactionBuilder,
field::Outputs,
};
use fuel_types::canonical::Deserialize;
use rand::{
Rng,
SeedableRng,
rngs::StdRng,
};
#[test]
fn external_balance() {
let mut rng = StdRng::seed_from_u64(2322u64);
let mut vm = Interpreter::<_, _, _>::with_memory_storage();
let gas_limit = 1_000_000;
let maturity = Default::default();
let height = Default::default();
let gas_price = 0;
let gas_costs = GasCosts::default();
let fee_params = *ConsensusParameters::standard().fee_params();
let script = op::ret(0x01).to_bytes().to_vec();
let balances = vec![(rng.r#gen(), 100), (rng.r#gen(), 500)];
let mut builder = TransactionBuilder::script(script, Default::default());
balances.iter().copied().for_each(|(asset, amount)| {
builder.add_unsigned_coin_input(
SecretKey::random(&mut rng),
rng.r#gen(),
amount,
asset,
rng.r#gen(),
);
});
let tx = builder
.script_gas_limit(gas_limit)
.script_gas_limit(100)
.maturity(maturity)
.finalize_checked(height)
.into_ready(gas_price, &gas_costs, &fee_params, None)
.unwrap();
vm.init_script(tx).expect("Failed to init VM!");
for (asset_id, amount) in balances {
assert!(
external_asset_id_balance_sub(
&mut vm.balances,
vm.memory.as_mut(),
&asset_id,
amount + 1,
)
.is_err()
);
external_asset_id_balance_sub(
&mut vm.balances,
vm.memory.as_mut(),
&asset_id,
amount - 10,
)
.unwrap();
assert!(
external_asset_id_balance_sub(
&mut vm.balances,
vm.memory.as_mut(),
&asset_id,
11,
)
.is_err()
);
external_asset_id_balance_sub(
&mut vm.balances,
vm.memory.as_mut(),
&asset_id,
10,
)
.unwrap();
assert!(
external_asset_id_balance_sub(
&mut vm.balances,
vm.memory.as_mut(),
&asset_id,
1,
)
.is_err()
);
}
}
#[test]
fn variable_output_updates_in_memory() {
let mut rng = StdRng::seed_from_u64(2322u64);
let zero_gas_price = 0;
let consensus_params = ConsensusParameters::standard();
let mut vm = Interpreter::<_, _, _>::with_storage(
MemoryInstance::new(),
MemoryStorage::default(),
InterpreterParams::new(zero_gas_price, &consensus_params),
);
let gas_limit = 1_000_000;
let height = Default::default();
let asset_id_to_update: AssetId = rng.r#gen();
let amount_to_set: Word = 100;
let owner: Address = rng.r#gen();
let variable_output = Output::Variable {
to: rng.r#gen(),
amount: 0,
asset_id: rng.r#gen(),
};
let tx = TransactionBuilder::script(vec![], vec![])
.script_gas_limit(gas_limit)
.add_fee_input()
.add_output(variable_output)
.finalize()
.into_checked(height, &consensus_params)
.expect("failed to check tx")
.into_ready(
zero_gas_price,
&GasCosts::default(),
consensus_params.fee_params(),
None,
)
.unwrap();
vm.init_script(tx).expect("Failed to init VM!");
let variable = Output::variable(owner, amount_to_set, asset_id_to_update);
let tx_offset = vm.tx_offset();
set_variable_output(&mut vm.tx, vm.memory.as_mut(), tx_offset, 0, variable).unwrap();
assert!(matches!(
vm.transaction().outputs()[0],
Output::Variable {amount, asset_id, to} if amount == amount_to_set
&& asset_id == asset_id_to_update
&& to == owner
));
let position = vm.tx_offset() + vm.transaction().outputs_offset_at(0).unwrap();
let mem_output = Output::decode(&mut &vm.memory().stack_raw()[position..]).unwrap();
assert_eq!(vm.transaction().outputs()[0], mem_output);
}