Ok thank you.
I am calculating the inputs/outputs manually since I lost a significant amount of ETH trying to run a script and not explicitly indicating the change outputs.
Do you have any theories why this breaks only when i run it on another machine?
I had issues with Wallet vs Unlocked when updating fuels-rs. I was not able to use Locked to make static calls with contracts / multicall. Not sure if that is relevant here.
Here is my function for calculating inputs/outputs:
ub async fn get_transaction_inputs_outputs(
wallet: &Wallet<Locked>,
assets_in: &[(AssetId, u64)],
gas_used: u64,
) -> Result<(Vec<Input>, Vec<Output>)> {
let mut inputs = Vec::new();
let mut outputs = Vec::new();
let base_asset = *tokens::ETH;
let gas_used = u128::from(gas_used);
let amount_in = u128::from(assets_in[0].1);
let asset_in = assets_in[0].0;
// Gather inputs for assets_in
for (asset, amount) in assets_in {
let mut amount = u128::from(*amount);
if amount == 0 {
panic!("amount in is 0");
}
if *asset == base_asset {
amount += gas_used;
}
let asset_inputs: Vec<Input> = wallet
.get_asset_inputs_for_amount(*asset, amount, None)
.await?;
let input_sum: u128 = asset_inputs
.iter()
.map(|i| u128::from(i.amount().unwrap_or(0)))
.sum();
// get change. difference of amount and sum
if input_sum > amount {
outputs.extend(wallet.get_asset_outputs_for_amount(
wallet.address(),
*asset,
u64::try_from(input_sum - amount)?,
));
}
if input_sum < amount_in {
return Err(anyhow!(
"Insufficient input for asset {:?}; required: {}, available: {}",
asset_in,
amount_in,
input_sum
));
}
inputs.extend(asset_inputs);
}
Ok((inputs, outputs))
}
And here is the context I am calling it:
pub async fn execute_swap(
wallets: (&Wallet<Unlocked<PrivateKeySigner>>, &Wallet<Locked>),
amount_in: u64,
amount_out_min: u64,
pools: Vec<DexSwap>,
path: Vec<AssetId>,
amounts_out_formatted: (Vec<u64>, Vec<u64>), // (out_0, out_1)
recipient: Address,
deadline: u32,
) -> Result<()> {
let (wallet_unlocked, wallet_locked) = wallets;
let script = get_swap_script_instance(wallet_unlocked)?;
let mira_amm = mira::Mira::new(*mira::AMM_CONTRACT, wallet_unlocked.clone());
let tx_policies = TxPolicies::default().with_script_gas_limit(GENERAL_SWAP_GAS_LIMIT);
let (inputs, outputs) = common::get_transaction_inputs_outputs(
wallet_locked,
&[(path[0], amount_in)],
GENERAL_SWAP_GAS_LIMIT,
)
.await?;
let mut call = script
.main(
amount_in,
amount_out_min,
pools.clone(),
path.clone(),
amounts_out_formatted.0.clone(),
amounts_out_formatted.1.clone(),
recipient.into(),
deadline,
)
.with_tx_policies(tx_policies)
.with_contracts(&[&mira_amm, &helper])
.with_inputs(inputs.clone())
.with_outputs(outputs.clone())
.with_variable_output_policy(VariableOutputPolicy::EstimateMinimum);
call.simulate(Execution::realistic()).await?;