diff --git a/.changelog/unreleased/SDK/1878-remove-sdk-fee-panics.md b/.changelog/unreleased/SDK/1878-remove-sdk-fee-panics.md new file mode 100644 index 0000000000..297572536c --- /dev/null +++ b/.changelog/unreleased/SDK/1878-remove-sdk-fee-panics.md @@ -0,0 +1,3 @@ +- Added two new variants to the `TxError` enum, `BalanceToLowForFees` and + `FeeUnshieldingError`, representing possible failures in transactions' fees. + ([\#1878](https://github.com/anoma/namada/pull/1878)) \ No newline at end of file diff --git a/.changelog/unreleased/bug-fixes/1878-remove-sdk-fee-panics.md b/.changelog/unreleased/bug-fixes/1878-remove-sdk-fee-panics.md new file mode 100644 index 0000000000..47eacd8dba --- /dev/null +++ b/.changelog/unreleased/bug-fixes/1878-remove-sdk-fee-panics.md @@ -0,0 +1,2 @@ +- Removed gas and fees related panics from the sdk. + ([\#1878](https://github.com/anoma/namada/pull/1878)) \ No newline at end of file diff --git a/shared/src/sdk/error.rs b/shared/src/sdk/error.rs index eb5f2b2d16..b103a9523f 100644 --- a/shared/src/sdk/error.rs +++ b/shared/src/sdk/error.rs @@ -189,6 +189,12 @@ pub enum TxError { to be transferred. Amount to transfer is {2} and the balance is {3}." )] BalanceTooLow(Address, Address, String, String), + /// Balance is too low for fee payment + #[error( + "The balance of the source {0} of token {1} is lower than the amount \ + required for fees. Amount of the fees is {2} and the balance is {3}." + )] + BalanceTooLowForFees(Address, Address, String, String), /// Token Address does not exist on chain #[error("The token address {0} doesn't exist on chain.")] TokenDoesNotExist(Address), @@ -213,6 +219,9 @@ pub enum TxError { /// No Balance found for token #[error("{0}")] MaspError(String), + /// Error in the fee unshielding transaction + #[error("Error in fee unshielding: {0}")] + FeeUnshieldingError(String), /// Wasm validation failed #[error("Validity predicate code validation failed with {0}")] WasmValidationFailure(WasmValidationError), diff --git a/shared/src/sdk/signing.rs b/shared/src/sdk/signing.rs index 145daa8213..042be03a63 100644 --- a/shared/src/sdk/signing.rs +++ b/shared/src/sdk/signing.rs @@ -23,6 +23,7 @@ use serde::{Deserialize, Serialize}; use sha2::Digest; use zeroize::Zeroizing; +use crate::display_line; use crate::ibc::applications::transfer::msgs::transfer::MsgTransfer; use crate::ibc_proto::google::protobuf::Any; use crate::ledger::parameters::storage as parameter_storage; @@ -54,7 +55,6 @@ use crate::types::transaction::governance::{ }; use crate::types::transaction::pos::InitValidator; use crate::types::transaction::Fee; -use crate::{display_line, edisplay_line}; #[cfg(feature = "std")] /// Env. var specifying where to store signing test vectors @@ -291,10 +291,11 @@ pub async fn aux_signing_data< }; if fee_payer == masp_tx_key().to_public() { - panic!( + other_err( "The gas payer cannot be the MASP, please provide a different gas \ payer." - ); + .to_string(), + )?; } Ok(SigningTxData { @@ -333,7 +334,7 @@ pub async fn wrap_tx< tx_source_balance: Option, epoch: Epoch, fee_payer: common::PublicKey, -) -> Option { +) -> Result, Error> { let fee_payer_address = Address::from(&fee_payer); // Validate fee amount and token let gas_cost_key = parameter_storage::get_gas_cost_key(); @@ -345,17 +346,17 @@ pub async fn wrap_tx< .and_then(|map| { map.get(&args.fee_token) .map(ToOwned::to_owned) - .ok_or_else(|| Error::Other("no fee found".to_string())) + .ok_or_else(|| { + Error::Other(format!( + "Could not retrieve from storage the gas cost for token {}", + args.fee_token + )) + }) }) { Ok(amount) => amount, - Err(_e) => { - edisplay_line!( - IO, - "Could not retrieve the gas cost for token {}", - args.fee_token - ); + Err(e) => { if !args.force { - panic!(); + return Err(e); } else { token::Amount::default() } @@ -481,30 +482,35 @@ pub async fn wrap_tx< > descriptions_limit && !args.force { - panic!( - "Fee unshielding descriptions exceed the limit" - ); + return Err(Error::from( + TxError::FeeUnshieldingError(format!( + "Descriptions exceed the limit: found \ + {descriptions}, limit \ + {descriptions_limit}" + )), + )); } updated_balance += total_fee; (Some(transaction), Some(unshielding_epoch)) } Ok(None) => { - edisplay_line!(IO, "Missing unshielding transaction"); if !args.force { - panic!(); + return Err(Error::from( + TxError::FeeUnshieldingError( + "Missing unshielding transaction" + .to_string(), + ), + )); } (None, None) } Err(e) => { - edisplay_line!( - IO, - "Error in fee unshielding generation: {}", - e - ); if !args.force { - panic!(); + return Err(Error::from( + TxError::FeeUnshieldingError(e.to_string()), + )); } (None, None) @@ -512,25 +518,26 @@ pub async fn wrap_tx< } } else { let token_addr = args.fee_token.clone(); - let err_msg = format!( - "The wrapper transaction source doesn't have enough \ - balance to pay fee {}, balance: {}.", - format_denominated_amount::<_, IO>( + if !args.force { + let fee_amount = format_denominated_amount::<_, IO>( client, &token_addr, - total_fee + total_fee, ) - .await, - format_denominated_amount::<_, IO>( + .await; + + let balance = format_denominated_amount::<_, IO>( client, &token_addr, - updated_balance + updated_balance, ) - .await, - ); - edisplay_line!(IO, "{}", err_msg); - if !args.force { - panic!("{}", err_msg); + .await; + return Err(Error::from(TxError::BalanceTooLowForFees( + fee_payer_address, + token_addr, + fee_amount, + balance, + ))); } (None, None) @@ -568,7 +575,7 @@ pub async fn wrap_tx< unshield_section_hash, ); - unshielding_epoch + Ok(unshielding_epoch) } #[allow(clippy::result_large_err)] diff --git a/shared/src/sdk/tx.rs b/shared/src/sdk/tx.rs index d333796922..9d7fe0cfe4 100644 --- a/shared/src/sdk/tx.rs +++ b/shared/src/sdk/tx.rs @@ -164,7 +164,7 @@ pub async fn prepare_tx< if !args.dry_run { let epoch = rpc::query_epoch(client).await?; - Ok(signing::wrap_tx::<_, _, IO>( + signing::wrap_tx::<_, _, IO>( client, shielded, tx, @@ -173,7 +173,7 @@ pub async fn prepare_tx< epoch, fee_payer, ) - .await) + .await } else { Ok(None) }