Skip to content

Commit

Permalink
fix: transaction builder no_input_to_cover_fees (#1302)
Browse files Browse the repository at this point in the history
The function `no_spendable_input` was not checking if the `asset_id` was
the base asset. Coins with other asset_ids can not be used to cover the
tx fee.
  • Loading branch information
hal3e authored Mar 29, 2024
1 parent e319a44 commit 96585fe
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 17 deletions.
6 changes: 4 additions & 2 deletions examples/types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ mod tests {

#[cfg(feature = "fuel-core-lib")]
use fuels::prelude::Config;
use fuels::prelude::Result;
use fuels::types::{Bits256, EvmAddress, Identity};
use fuels::{
prelude::Result,
types::{Bits256, EvmAddress, Identity},
};

#[tokio::test]
async fn bytes32() -> Result<()> {
Expand Down
34 changes: 19 additions & 15 deletions packages/fuels-core/src/types/transaction_builders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use fuel_asm::{op, GTFArgs, RegId};
use fuel_crypto::{Message as CryptoMessage, Signature};
use fuel_tx::{
field::{Inputs, Policies as PoliciesField, WitnessLimit, Witnesses},
input::coin::{CoinPredicate, CoinSigned},
policies::{Policies, PolicyType},
Buildable, Chargeable, ConsensusParameters, Create, Input as FuelInput, Output, Script,
StorageSlot, Transaction as FuelTransaction, TransactionFee, TxPointer, UniqueIdentifier,
Expand Down Expand Up @@ -405,16 +406,19 @@ impl ScriptTransactionBuilder {
.collect()
}

fn no_spendable_input<'a, I: IntoIterator<Item = &'a FuelInput>>(inputs: I) -> bool {
!inputs.into_iter().any(|i| {
matches!(
i,
FuelInput::CoinSigned(_)
| FuelInput::CoinPredicate(_)
| FuelInput::MessageCoinSigned(_)
| FuelInput::MessageCoinPredicate(_)
)
})
fn no_base_asset_input<'a, I: IntoIterator<Item = &'a FuelInput>>(inputs: I) -> bool {
let has_base_asset = inputs.into_iter().any(|i| match i {
FuelInput::CoinSigned(CoinSigned { asset_id, .. })
| FuelInput::CoinPredicate(CoinPredicate { asset_id, .. })
if *asset_id == BASE_ASSET_ID =>
{
true
}
FuelInput::MessageCoinSigned(_) | FuelInput::MessageCoinPredicate(_) => true,
_ => false,
});

!has_base_asset
}

async fn set_script_gas_limit_to_gas_used(
Expand All @@ -424,10 +428,10 @@ impl ScriptTransactionBuilder {
) -> Result<()> {
let consensus_params = provider.consensus_parameters();

// The dry-run validation will check if there is any spendable input present in
// the transaction. If we are dry-running without inputs we have to add a temporary one.
let no_spendable_input = Self::no_spendable_input(tx.inputs());
if no_spendable_input {
// The dry-run validation will check if there is any base asset input.
// If we are dry-running without inputs we have to add a temporary one.
let no_base_asset_input = Self::no_base_asset_input(tx.inputs());
if no_base_asset_input {
tx.inputs_mut().push(FuelInput::coin_signed(
Default::default(),
Default::default(),
Expand All @@ -453,7 +457,7 @@ impl ScriptTransactionBuilder {
.await?;

// Remove dry-run input and witness.
if no_spendable_input {
if no_base_asset_input {
tx.inputs_mut().pop();
tx.witnesses_mut().pop();
tx.set_witness_limit(tx.witness_limit() - WITNESS_STATIC_SIZE as u64);
Expand Down

0 comments on commit 96585fe

Please sign in to comment.