From b3ed7bacd700357a10c42418d43c4022986ecb29 Mon Sep 17 00:00:00 2001 From: laruh Date: Thu, 26 Sep 2024 20:18:37 +0700 Subject: [PATCH] review: gas limit traits --- mm2src/coins/eth.rs | 80 +++++++++++++++++++ .../eth/eth_swap_v2/eth_maker_swap_v2.rs | 64 ++++++--------- .../eth/eth_swap_v2/eth_taker_swap_v2.rs | 60 ++++++-------- mm2src/coins/eth/eth_swap_v2/mod.rs | 9 ++- mm2src/coins/eth/nft_swap_v2/mod.rs | 34 ++++---- 5 files changed, 152 insertions(+), 95 deletions(-) diff --git a/mm2src/coins/eth.rs b/mm2src/coins/eth.rs index 8107c90e52..9612efeec3 100644 --- a/mm2src/coins/eth.rs +++ b/mm2src/coins/eth.rs @@ -158,6 +158,7 @@ pub(crate) use eip1559_gas_fee::FeePerGasEstimated; use eip1559_gas_fee::{BlocknativeGasApiCaller, FeePerGasSimpleEstimator, GasApiConfig, GasApiProvider, InfuraGasApiCaller}; pub(crate) mod eth_swap_v2; +use eth_swap_v2::{EthPaymentType, PaymentMethod}; /// https://github.com/artemii235/etomic-swap/blob/master/contracts/EtomicSwap.sol /// Dev chain (195.201.137.5:8565) contract address: 0x83965C539899cC0F918552e5A26915de40ee8852 @@ -378,6 +379,85 @@ pub struct NftMakerGasLimitV2 { pub erc1155_maker_refund_secret: u64, } +pub trait NftGasLimit { + fn nft_gas_limit(&self, contract_type: &ContractType, method: PaymentMethod) -> u64; +} + +impl NftGasLimit for EthGasLimitV2 { + fn nft_gas_limit(&self, contract_type: &ContractType, method: PaymentMethod) -> u64 { + match contract_type { + ContractType::Erc1155 => match method { + PaymentMethod::Send => self.nft_maker.erc1155_payment, + PaymentMethod::Spend => self.nft_maker.erc1155_taker_spend, + PaymentMethod::RefundTimelock => self.nft_maker.erc1155_maker_refund_timelock, + PaymentMethod::RefundSecret => self.nft_maker.erc1155_maker_refund_secret, + }, + ContractType::Erc721 => match method { + PaymentMethod::Send => self.nft_maker.erc721_payment, + PaymentMethod::Spend => self.nft_maker.erc721_taker_spend, + PaymentMethod::RefundTimelock => self.nft_maker.erc721_maker_refund_timelock, + PaymentMethod::RefundSecret => self.nft_maker.erc721_maker_refund_secret, + }, + } + } +} + +pub trait GasLimit { + fn gas_limit( + &self, + coin_type: &EthCoinType, + payment_type: EthPaymentType, + method: PaymentMethod, + ) -> Result<(Address, u64), String>; +} + +impl GasLimit for EthGasLimitV2 { + fn gas_limit( + &self, + coin_type: &EthCoinType, + payment_type: EthPaymentType, + method: PaymentMethod, + ) -> Result<(Address, u64), String> { + match coin_type { + EthCoinType::Eth => { + let gas_limit = match payment_type { + EthPaymentType::MakerPayments => match method { + PaymentMethod::Send => self.maker.eth_payment, + PaymentMethod::Spend => self.maker.eth_taker_spend, + PaymentMethod::RefundTimelock => self.maker.eth_maker_refund_timelock, + PaymentMethod::RefundSecret => self.maker.eth_maker_refund_secret, + }, + EthPaymentType::TakerPayments => match method { + PaymentMethod::Send => self.taker.eth_payment, + PaymentMethod::Spend => self.taker.eth_maker_spend, + PaymentMethod::RefundTimelock => self.taker.eth_taker_refund_timelock, + PaymentMethod::RefundSecret => self.taker.eth_taker_refund_secret, + }, + }; + Ok((Address::default(), gas_limit)) + }, + EthCoinType::Erc20 { token_addr, .. } => { + let gas_limit = match payment_type { + EthPaymentType::MakerPayments => match method { + PaymentMethod::Send => self.maker.erc20_payment, + PaymentMethod::Spend => self.maker.erc20_taker_spend, + PaymentMethod::RefundTimelock => self.maker.erc20_maker_refund_timelock, + PaymentMethod::RefundSecret => self.maker.erc20_maker_refund_secret, + }, + EthPaymentType::TakerPayments => match method { + PaymentMethod::Send => self.taker.erc20_payment, + PaymentMethod::Spend => self.taker.erc20_maker_spend, + PaymentMethod::RefundTimelock => self.taker.erc20_taker_refund_timelock, + PaymentMethod::RefundSecret => self.taker.erc20_taker_refund_secret, + }, + }; + Ok((*token_addr, gas_limit)) + }, + EthCoinType::Nft { .. } => Err("NFT protocol is not supported for ETH and ERC20 Swaps".to_string()), + } + } +} + impl Default for MakerGasLimitV2 { fn default() -> Self { MakerGasLimitV2 { diff --git a/mm2src/coins/eth/eth_swap_v2/eth_maker_swap_v2.rs b/mm2src/coins/eth/eth_swap_v2/eth_maker_swap_v2.rs index 0313d1d7fc..deb0e7224d 100644 --- a/mm2src/coins/eth/eth_swap_v2/eth_maker_swap_v2.rs +++ b/mm2src/coins/eth/eth_swap_v2/eth_maker_swap_v2.rs @@ -1,6 +1,7 @@ -use super::{validate_from_to_and_status, validate_payment_args, EthPaymentType, PrepareTxDataError, ZERO_VALUE}; +use super::{validate_from_to_and_status, validate_payment_args, EthPaymentType, PaymentMethod, PrepareTxDataError, + ZERO_VALUE}; use crate::coin_errors::{ValidatePaymentError, ValidatePaymentResult}; -use crate::eth::{decode_contract_call, get_function_input_data, wei_from_big_decimal, EthCoin, EthCoinType, +use crate::eth::{decode_contract_call, get_function_input_data, wei_from_big_decimal, EthCoin, EthCoinType, GasLimit, MakerPaymentStateV2, SignedEthTx, MAKER_SWAP_V2}; use crate::{ParseCoinAssocTypes, RefundMakerPaymentSecretArgs, RefundMakerPaymentTimelockArgs, SendMakerPaymentArgs, SpendMakerPaymentArgs, SwapTxTypeWithSecretHash, TransactionErr, ValidateMakerPaymentArgs, @@ -181,18 +182,14 @@ impl EthCoin { &self, args: RefundMakerPaymentTimelockArgs<'_>, ) -> Result { - let (token_address, gas_limit) = match &self.coin_type { - EthCoinType::Eth => (Address::default(), self.gas_limit_v2.maker.eth_maker_refund_timelock), - EthCoinType::Erc20 { - platform: _, - token_addr, - } => (*token_addr, self.gas_limit_v2.maker.erc20_maker_refund_timelock), - EthCoinType::Nft { .. } => { - return Err(TransactionErr::ProtocolNotSupported(ERRL!( - "NFT protocol is not supported for ETH and ERC20 Swaps" - ))) - }, - }; + let (token_address, gas_limit) = self + .gas_limit_v2 + .gas_limit( + &self.coin_type, + EthPaymentType::MakerPayments, + PaymentMethod::RefundTimelock, + ) + .map_err(|e| TransactionErr::Plain(ERRL!("{}", e)))?; let maker_swap_v2_contract = self .swap_v2_contracts @@ -239,18 +236,14 @@ impl EthCoin { &self, args: RefundMakerPaymentSecretArgs<'_, Self>, ) -> Result { - let (token_address, gas_limit) = match &self.coin_type { - EthCoinType::Eth => (Address::default(), self.gas_limit_v2.maker.eth_maker_refund_secret), - EthCoinType::Erc20 { - platform: _, - token_addr, - } => (*token_addr, self.gas_limit_v2.maker.erc20_maker_refund_secret), - EthCoinType::Nft { .. } => { - return Err(TransactionErr::ProtocolNotSupported(ERRL!( - "NFT protocol is not supported for ETH and ERC20 Swaps" - ))) - }, - }; + let (token_address, gas_limit) = self + .gas_limit_v2 + .gas_limit( + &self.coin_type, + EthPaymentType::MakerPayments, + PaymentMethod::RefundSecret, + ) + .map_err(|e| TransactionErr::Plain(ERRL!("{}", e)))?; let maker_swap_v2_contract = self .swap_v2_contracts @@ -288,18 +281,11 @@ impl EthCoin { &self, args: SpendMakerPaymentArgs<'_, Self>, ) -> Result { - let (token_address, gas_limit) = match &self.coin_type { - EthCoinType::Eth => (Address::default(), U256::from(self.gas_limit_v2.maker.eth_taker_spend)), - EthCoinType::Erc20 { - platform: _, - token_addr, - } => (*token_addr, U256::from(self.gas_limit_v2.maker.erc20_taker_spend)), - EthCoinType::Nft { .. } => { - return Err(TransactionErr::ProtocolNotSupported(ERRL!( - "NFT protocol is not supported for ETH and ERC20 Swaps" - ))) - }, - }; + let (token_address, gas_limit) = self + .gas_limit_v2 + .gas_limit(&self.coin_type, EthPaymentType::MakerPayments, PaymentMethod::Spend) + .map_err(|e| TransactionErr::Plain(ERRL!("{}", e)))?; + let maker_swap_v2_contract = self .swap_v2_contracts .as_ref() @@ -312,7 +298,7 @@ impl EthCoin { U256::from(ZERO_VALUE), Action::Call(maker_swap_v2_contract), data, - gas_limit, + U256::from(gas_limit), ) .compat() .await diff --git a/mm2src/coins/eth/eth_swap_v2/eth_taker_swap_v2.rs b/mm2src/coins/eth/eth_swap_v2/eth_taker_swap_v2.rs index 56eb5dcf4e..f0cfdc8eea 100644 --- a/mm2src/coins/eth/eth_swap_v2/eth_taker_swap_v2.rs +++ b/mm2src/coins/eth/eth_swap_v2/eth_taker_swap_v2.rs @@ -1,6 +1,6 @@ use super::{check_decoded_length, validate_from_to_and_status, validate_payment_args, validate_payment_state, - EthPaymentType, PrepareTxDataError, ZERO_VALUE}; -use crate::eth::{decode_contract_call, get_function_input_data, wei_from_big_decimal, EthCoin, EthCoinType, + EthPaymentType, PaymentMethod, PrepareTxDataError, ZERO_VALUE}; +use crate::eth::{decode_contract_call, get_function_input_data, wei_from_big_decimal, EthCoin, EthCoinType, GasLimit, ParseCoinAssocTypes, RefundFundingSecretArgs, RefundTakerPaymentArgs, SendTakerFundingArgs, SignedEthTx, SwapTxTypeWithSecretHash, TakerPaymentStateV2, TransactionErr, ValidateSwapV2TxError, ValidateSwapV2TxResult, ValidateTakerFundingArgs, TAKER_SWAP_V2}; @@ -246,18 +246,14 @@ impl EthCoin { &self, args: RefundTakerPaymentArgs<'_>, ) -> Result { - let (token_address, gas_limit) = match &self.coin_type { - EthCoinType::Eth => (Address::default(), self.gas_limit_v2.taker.eth_taker_refund_timelock), - EthCoinType::Erc20 { - platform: _, - token_addr, - } => (*token_addr, self.gas_limit_v2.taker.erc20_taker_refund_timelock), - EthCoinType::Nft { .. } => { - return Err(TransactionErr::ProtocolNotSupported(ERRL!( - "NFT protocol is not supported for ETH and ERC20 Swaps" - ))) - }, - }; + let (token_address, gas_limit) = self + .gas_limit_v2 + .gas_limit( + &self.coin_type, + EthPaymentType::TakerPayments, + PaymentMethod::RefundTimelock, + ) + .map_err(|e| TransactionErr::Plain(ERRL!("{}", e)))?; let taker_swap_v2_contract = self .swap_v2_contracts @@ -311,18 +307,14 @@ impl EthCoin { &self, args: RefundFundingSecretArgs<'_, Self>, ) -> Result { - let (token_address, gas_limit) = match &self.coin_type { - EthCoinType::Eth => (Address::default(), self.gas_limit_v2.taker.eth_taker_refund_secret), - EthCoinType::Erc20 { - platform: _, - token_addr, - } => (*token_addr, self.gas_limit_v2.taker.erc20_taker_refund_secret), - EthCoinType::Nft { .. } => { - return Err(TransactionErr::ProtocolNotSupported(ERRL!( - "NFT protocol is not supported for ETH and ERC20 Swaps" - ))) - }, - }; + let (token_address, gas_limit) = self + .gas_limit_v2 + .gas_limit( + &self.coin_type, + EthPaymentType::TakerPayments, + PaymentMethod::RefundSecret, + ) + .map_err(|e| TransactionErr::Plain(ERRL!("{}", e)))?; let taker_swap_v2_contract = self .swap_v2_contracts @@ -396,15 +388,11 @@ impl EthCoin { gen_args: &GenTakerPaymentSpendArgs<'_, Self>, secret: &[u8], ) -> Result { - let gas_limit = match self.coin_type { - EthCoinType::Eth => U256::from(self.gas_limit_v2.taker.eth_maker_spend), - EthCoinType::Erc20 { .. } => U256::from(self.gas_limit_v2.taker.erc20_maker_spend), - EthCoinType::Nft { .. } => { - return Err(TransactionErr::ProtocolNotSupported(ERRL!( - "NFT protocol is not supported for ETH and ERC20 Swaps" - ))) - }, - }; + let (_, gas_limit) = self + .gas_limit_v2 + .gas_limit(&self.coin_type, EthPaymentType::TakerPayments, PaymentMethod::Spend) + .map_err(|e| TransactionErr::Plain(ERRL!("{}", e)))?; + let (taker_swap_v2_contract, approve_func, token_address) = self .taker_swap_v2_details(TAKER_PAYMENT_APPROVE, TAKER_PAYMENT_APPROVE) .await?; @@ -434,7 +422,7 @@ impl EthCoin { U256::from(ZERO_VALUE), Action::Call(taker_swap_v2_contract), data, - gas_limit, + U256::from(gas_limit), ) .compat() .await?; diff --git a/mm2src/coins/eth/eth_swap_v2/mod.rs b/mm2src/coins/eth/eth_swap_v2/mod.rs index 9882decb6f..8e099c236c 100644 --- a/mm2src/coins/eth/eth_swap_v2/mod.rs +++ b/mm2src/coins/eth/eth_swap_v2/mod.rs @@ -18,7 +18,7 @@ pub(crate) mod eth_taker_swap_v2; /// is provided as part of the input data rather than as an Ether value pub(crate) const ZERO_VALUE: u32 = 0; -pub(crate) enum EthPaymentType { +pub enum EthPaymentType { MakerPayments, TakerPayments, } @@ -32,6 +32,13 @@ impl EthPaymentType { } } +pub enum PaymentMethod { + Send, + Spend, + RefundTimelock, + RefundSecret, +} + #[derive(Debug, Display)] pub(crate) enum ValidatePaymentV2Err { UnexpectedPaymentState(String), diff --git a/mm2src/coins/eth/nft_swap_v2/mod.rs b/mm2src/coins/eth/nft_swap_v2/mod.rs index 174c53dd4f..96d35b4ab6 100644 --- a/mm2src/coins/eth/nft_swap_v2/mod.rs +++ b/mm2src/coins/eth/nft_swap_v2/mod.rs @@ -14,9 +14,9 @@ use errors::{Erc721FunctionError, HtlcParamsError}; mod structs; use structs::{ExpectedHtlcParams, ValidationParams}; -use super::ContractType; -use crate::eth::eth_swap_v2::{validate_from_to_and_status, validate_payment_state, EthPaymentType, PaymentStatusErr, - PrepareTxDataError, ZERO_VALUE}; +use super::{ContractType, NftGasLimit}; +use crate::eth::eth_swap_v2::{validate_from_to_and_status, validate_payment_state, EthPaymentType, PaymentMethod, + PaymentStatusErr, PrepareTxDataError, ZERO_VALUE}; use crate::eth::{decode_contract_call, EthCoin, EthCoinType, MakerPaymentStateV2, SignedEthTx, ERC1155_CONTRACT, ERC721_CONTRACT, NFT_MAKER_SWAP_V2}; use crate::{ParseCoinAssocTypes, RefundNftMakerPaymentArgs, SendNftMakerPaymentArgs, SpendNftMakerPaymentArgs, @@ -38,10 +38,9 @@ impl EthCoin { let htlc_data = try_tx_s!(self.prepare_htlc_data(&args)); let data = try_tx_s!(self.prepare_nft_maker_payment_v2_data(&args, htlc_data).await); - let gas_limit = match args.nft_swap_info.contract_type { - ContractType::Erc1155 => self.gas_limit_v2.nft_maker.erc1155_payment, - ContractType::Erc721 => self.gas_limit_v2.nft_maker.erc721_payment, - }; + let gas_limit = self + .gas_limit_v2 + .nft_gas_limit(args.nft_swap_info.contract_type, PaymentMethod::Send); self.sign_and_send_transaction( ZERO_VALUE.into(), Action::Call(*args.nft_swap_info.token_address), @@ -178,10 +177,9 @@ impl EthCoin { .await ); let data = try_tx_s!(self.prepare_spend_nft_maker_v2_data(&args, decoded, htlc_params, state)); - let gas_limit = match args.contract_type { - ContractType::Erc1155 => self.gas_limit_v2.nft_maker.erc1155_taker_spend, - ContractType::Erc721 => self.gas_limit_v2.nft_maker.erc721_taker_spend, - }; + let gas_limit = self + .gas_limit_v2 + .nft_gas_limit(args.contract_type, PaymentMethod::Spend); self.sign_and_send_transaction( ZERO_VALUE.into(), Action::Call(nft_maker_swap_v2_contract), @@ -228,10 +226,9 @@ impl EthCoin { ); let data = try_tx_s!(self.prepare_refund_nft_maker_payment_v2_timelock(&args, decoded, htlc_params, state)); - let gas_limit = match args.contract_type { - ContractType::Erc1155 => self.gas_limit_v2.nft_maker.erc1155_maker_refund_timelock, - ContractType::Erc721 => self.gas_limit_v2.nft_maker.erc721_maker_refund_timelock, - }; + let gas_limit = self + .gas_limit_v2 + .nft_gas_limit(args.contract_type, PaymentMethod::RefundTimelock); self.sign_and_send_transaction( ZERO_VALUE.into(), Action::Call(nft_maker_swap_v2_contract), @@ -279,10 +276,9 @@ impl EthCoin { let data = try_tx_s!(self.prepare_refund_nft_maker_payment_v2_secret(&args, decoded, htlc_params, state)); - let gas_limit = match args.contract_type { - ContractType::Erc1155 => self.gas_limit_v2.nft_maker.erc1155_maker_refund_secret, - ContractType::Erc721 => self.gas_limit_v2.nft_maker.erc721_maker_refund_secret, - }; + let gas_limit = self + .gas_limit_v2 + .nft_gas_limit(args.contract_type, PaymentMethod::RefundSecret); self.sign_and_send_transaction( ZERO_VALUE.into(), Action::Call(nft_maker_swap_v2_contract),