Skip to content

Commit

Permalink
bug: script/predicate blob upload now uses the default max fee estima…
Browse files Browse the repository at this point in the history
…tion tolerance (#1590)

because the gas price horizon no longer increases the price and this makes the max fee estimation more sensitive to extra cost due to using more coins than what we estimated with.
  • Loading branch information
segfault-magnet authored Jan 30, 2025
1 parent 482897e commit 3f59bf6
Show file tree
Hide file tree
Showing 11 changed files with 99 additions and 18 deletions.
5 changes: 3 additions & 2 deletions e2e/tests/contracts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use fuel_tx::{
use fuels::{
core::codec::{calldata, encode_fn_selector, DecoderConfig, EncoderConfig},
prelude::*,
programs::DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE,
tx::ContractParameters,
types::{errors::transaction::Reason, input::Input, Bits256, Identity},
};
Expand Down Expand Up @@ -2114,8 +2115,8 @@ async fn max_fee_estimation_respects_tolerance() -> Result<()> {
.unwrap();

assert_eq!(
builder.max_fee_estimation_tolerance, 0.05,
"Expected pre-set tolerance of 0.05"
builder.max_fee_estimation_tolerance, DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE,
"Expected pre-set tolerance"
);

builder
Expand Down
69 changes: 68 additions & 1 deletion e2e/tests/scripts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ use std::time::Duration;

use fuel_tx::Output;
use fuels::{
client::{PageDirection, PaginationRequest},
core::{
codec::{DecoderConfig, EncoderConfig},
traits::Tokenizable,
Configurables,
},
prelude::*,
programs::executable::Executable,
programs::{executable::Executable, DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE},
types::{Bits256, Identity},
};

Expand Down Expand Up @@ -489,6 +490,72 @@ async fn can_be_run_in_blobs_high_level() -> Result<()> {
Ok(())
}

#[tokio::test]
async fn high_level_blob_upload_sets_max_fee_tolerance() -> Result<()> {
let node_config = NodeConfig {
starting_gas_price: 1000000000,
..Default::default()
};
let mut wallet = WalletUnlocked::new_random(None);
let coins = setup_single_asset_coins(wallet.address(), AssetId::zeroed(), 1, u64::MAX);
let provider = setup_test_provider(coins, vec![], Some(node_config), None).await?;
wallet.set_provider(provider.clone());

setup_program_test!(
Abigen(Script(
project = "e2e/sway/scripts/script_blobs",
name = "MyScript"
)),
LoadScript(name = "my_script", script = "MyScript", wallet = "wallet")
);

let loader = Executable::from_bytes(std::fs::read(
"sway/scripts/script_blobs/out/release/script_blobs.bin",
)?)
.convert_to_loader()?;

let zero_tolerance_fee = {
let mut tb = BlobTransactionBuilder::default()
.with_blob(loader.blob())
.with_max_fee_estimation_tolerance(0.);

wallet.adjust_for_fee(&mut tb, 0).await?;

wallet.add_witnesses(&mut tb)?;
let tx = tb.build(&provider).await?;
tx.max_fee().unwrap()
};

let mut my_script = my_script;
my_script.convert_into_loader().await?;

let max_fee_of_sent_blob_tx = provider
.get_transactions(PaginationRequest {
cursor: None,
results: 100,
direction: PageDirection::Forward,
})
.await?
.results
.into_iter()
.find_map(|tx| {
if let TransactionType::Blob(blob_transaction) = tx.transaction {
blob_transaction.max_fee()
} else {
None
}
})
.unwrap();

assert_eq!(
max_fee_of_sent_blob_tx,
(zero_tolerance_fee as f32 * (1.0 + DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE)).ceil() as u64,
"the blob upload tx should have had the max fee increased by the default estimation tolerance"
);

Ok(())
}

#[tokio::test]
async fn no_data_section_blob_run() -> Result<()> {
setup_program_test!(
Expand Down
2 changes: 1 addition & 1 deletion packages/fuels-accounts/src/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -758,7 +758,7 @@ impl Provider {
let receipts = self.dry_run_opt(tx, false, None).await?.take_receipts();
let gas_used = self.get_script_gas_used(&receipts);

Ok((gas_used as f64 * (1.0 + tolerance)) as u64)
Ok((gas_used as f64 * (1.0 + tolerance)).ceil() as u64)
}

fn get_script_gas_used(&self, receipts: &[Receipt]) -> u64 {
Expand Down
2 changes: 1 addition & 1 deletion packages/fuels-core/src/types/dry_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ impl DryRun {
pub fn gas_with_tolerance(&self, tolerance: f32) -> u64 {
let gas_used = self.script_gas as f64;
let adjusted_gas = gas_used * (1.0 + f64::from(tolerance));
adjusted_gas as u64
adjusted_gas.ceil() as u64
}
}

Expand Down
2 changes: 1 addition & 1 deletion packages/fuels-core/src/types/transaction_builders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ pub(crate) fn estimate_max_fee_w_tolerance<T: Chargeable>(

let max_fee_w_tolerance = tx_fee.max_fee() as f64 * (1.0 + f64::from(tolerance));

Ok(max_fee_w_tolerance as u64)
Ok(max_fee_w_tolerance.ceil() as u64)
}

impl Debug for dyn Signer + Send + Sync {
Expand Down
13 changes: 8 additions & 5 deletions packages/fuels-programs/src/calls/traits/transaction_tuner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ use fuels_core::types::{
},
};

use crate::calls::{
utils::{build_tx_from_contract_calls, sealed, transaction_builder_from_contract_calls},
ContractCall, ScriptCall,
use crate::{
calls::{
utils::{build_tx_from_contract_calls, sealed, transaction_builder_from_contract_calls},
ContractCall, ScriptCall,
},
DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE,
};

#[async_trait::async_trait]
Expand Down Expand Up @@ -79,8 +82,8 @@ impl TransactionTuner for ScriptCall {
.with_script_data(self.compute_script_data()?)
.with_inputs(inputs)
.with_outputs(outputs)
.with_gas_estimation_tolerance(0.05)
.with_max_fee_estimation_tolerance(0.05))
.with_gas_estimation_tolerance(DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE)
.with_max_fee_estimation_tolerance(DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE))
}

async fn build_tx<T: Account>(
Expand Down
5 changes: 3 additions & 2 deletions packages/fuels-programs/src/calls/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use itertools::{chain, Itertools};
use crate::{
assembly::contract_call::{CallOpcodeParamsOffset, ContractCallInstructions},
calls::ContractCall,
DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE,
};

pub(crate) mod sealed {
Expand Down Expand Up @@ -73,8 +74,8 @@ pub(crate) async fn transaction_builder_from_contract_calls(
.with_script_data(script_data.clone())
.with_inputs(inputs)
.with_outputs(outputs)
.with_gas_estimation_tolerance(0.05)
.with_max_fee_estimation_tolerance(0.05))
.with_gas_estimation_tolerance(DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE)
.with_max_fee_estimation_tolerance(DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE))
}

/// Creates a [`ScriptTransaction`] from contract calls. The internal [Transaction] is
Expand Down
4 changes: 2 additions & 2 deletions packages/fuels-programs/src/contract/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use fuels_core::{
},
};

use crate::assembly::contract_call::loader_contract_asm;
use crate::{assembly::contract_call::loader_contract_asm, DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE};

use super::{compute_contract_id_and_state_root, Contract, Regular};

Expand Down Expand Up @@ -138,7 +138,7 @@ impl Contract<Loader<BlobsNotUploaded>> {
let mut tb = BlobTransactionBuilder::default()
.with_blob(blob)
.with_tx_policies(tx_policies)
.with_max_fee_estimation_tolerance(0.05);
.with_max_fee_estimation_tolerance(DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE);

account.adjust_for_fee(&mut tb, 0).await?;
account.add_witnesses(&mut tb)?;
Expand Down
4 changes: 3 additions & 1 deletion packages/fuels-programs/src/contract/regular.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ use fuels_core::{
Configurables,
};

use crate::DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE;

use super::{
compute_contract_id_and_state_root, validate_path_and_extension, BlobsNotUploaded, Contract,
Loader, StorageConfiguration,
Expand Down Expand Up @@ -152,7 +154,7 @@ impl Contract<Regular> {
storage_slots.to_vec(),
tx_policies,
)
.with_max_fee_estimation_tolerance(0.05);
.with_max_fee_estimation_tolerance(DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE);

account.add_witnesses(&mut tb)?;
account.adjust_for_fee(&mut tb, 0).await?;
Expand Down
9 changes: 7 additions & 2 deletions packages/fuels-programs/src/executable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ use fuels_core::{
Configurables,
};

use crate::assembly::script_and_predicate_loader::{extract_data_offset, LoaderCode};
use crate::{
assembly::script_and_predicate_loader::{extract_data_offset, LoaderCode},
DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE,
};

/// This struct represents a standard executable with its associated bytecode and configurables.
#[derive(Debug, Clone, PartialEq)]
Expand Down Expand Up @@ -151,7 +154,9 @@ impl Executable<Loader> {
return Ok(());
}

let mut tb = BlobTransactionBuilder::default().with_blob(self.blob());
let mut tb = BlobTransactionBuilder::default()
.with_blob(self.blob())
.with_max_fee_estimation_tolerance(DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE);

account.adjust_for_fee(&mut tb, 0).await?;

Expand Down
2 changes: 2 additions & 0 deletions packages/fuels-programs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ pub mod executable;
#[cfg(feature = "std")]
pub mod responses;

pub const DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE: f32 = 0.50;

pub mod debug;

pub(crate) mod assembly;
Expand Down

0 comments on commit 3f59bf6

Please sign in to comment.