Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(eth-swap): maker tpu v2 implementation #2211

Merged
merged 48 commits into from
Nov 8, 2024
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
e485de2
create eth_swap_v2 module, and refactor eth_swap_v2.rs to eth_taker_s…
laruh Aug 20, 2024
6593dc7
maker ops: send_maker_payment_v2_impl added
laruh Aug 28, 2024
9eac0fd
WIP: validate_maker_payment_v2_impl
laruh Aug 30, 2024
4fc3971
remove unused import
laruh Aug 30, 2024
45d4726
maker tpu v2: validate_maker_payment_v2_impl
laruh Aug 30, 2024
619359a
maker tpu v2: refund timelock and secret
laruh Sep 1, 2024
a6e17b4
maker tpu v2: wait_for_maker_payment_spend TODO
laruh Sep 1, 2024
e16bf49
maker tpu v2: spend_maker_payment_v2_impl
laruh Sep 2, 2024
b35e68f
eth maker tpu v2: wait_for_maker_payment_spend_impl
laruh Sep 2, 2024
f73b5de
eth maker v2 docker tests
laruh Sep 3, 2024
e53c028
remove clone for now
laruh Sep 5, 2024
3815d08
Merge remote-tracking branch 'origin/dev' into eth-maker-tpu-v2
laruh Sep 5, 2024
7498eec
maker swap v2 docker tests (on sepolia)
laruh Sep 8, 2024
b1626f7
set taker and maker gas limits V2
laruh Sep 9, 2024
ce7903d
taker gas limits v2
laruh Sep 10, 2024
f1063c7
move prepare erc20 payment data above allowance, impl handle_allowance
laruh Sep 10, 2024
60f11f8
start using `nft_maker_swap_v2_contract` from EthCoin in Nft maker sw…
laruh Sep 10, 2024
0c96992
nft maker gas limits v2
laruh Sep 11, 2024
8f983ec
update taker time
laruh Sep 11, 2024
6961d50
update gas limit fields names
laruh Sep 16, 2024
5d9d1de
add sepolia test features
laruh Sep 16, 2024
d57abdb
Merge remote-tracking branch 'origin/dev' into eth-maker-tpu-v2
laruh Sep 19, 2024
1ef0f43
provide SEPOLIA_TESTS_LOCK
laruh Sep 19, 2024
638afd2
UtxoStandardCoin wait_for_maker_payment_spend
laruh Sep 24, 2024
be1eab0
call crate BigDecimal method is_positive
laruh Sep 25, 2024
4bada4f
Merge remote-tracking branch 'origin/dev' into eth-maker-tpu-v2
laruh Sep 25, 2024
ab0f961
fix clippy
laruh Sep 26, 2024
b3ed7ba
review: gas limit traits
laruh Sep 26, 2024
9b388a2
Merge remote-tracking branch 'origin/dev' into eth-maker-tpu-v2
laruh Oct 3, 2024
3dce044
review: remove traits
laruh Oct 7, 2024
eeead52
Merge remote-tracking branch 'origin/dev' into eth-maker-tpu-v2
laruh Oct 7, 2024
f7eab3c
Merge remote-tracking branch 'origin/dev' into eth-maker-tpu-v2
laruh Oct 15, 2024
5f1e38c
Merge remote-tracking branch 'origin/dev' into eth-maker-tpu-v2
laruh Oct 24, 2024
a5a0834
Merge remote-tracking branch 'origin/dev' into eth-maker-tpu-v2
laruh Oct 24, 2024
db6b2e7
remove wait_for_maker_payment_spend
laruh Nov 1, 2024
da12b97
increase v2 ERC20_PAYMENT consts to 150_000
laruh Nov 1, 2024
2b81855
review: consts for TAKER/MAKER state indexes
laruh Nov 1, 2024
72ed306
review: create separate Refund Args structures for Timelock and Secre…
laruh Nov 1, 2024
a9a5c47
review: remove unreachable
laruh Nov 3, 2024
1ccfc77
review: split token_address and gas_limit funcs logic
laruh Nov 3, 2024
6e42e34
review: adjust gas limit consts
laruh Nov 3, 2024
1e6dacb
Merge remote-tracking branch 'origin/dev' into eth-maker-tpu-v2
laruh Nov 4, 2024
ce15cd8
review: prioritize errors
laruh Nov 4, 2024
57e75ed
review: remove unnecessary as_ref, map functions
laruh Nov 4, 2024
1e6ea8e
review: use ref to a fixed-size array in Validation Args
laruh Nov 4, 2024
77b7500
Merge remote-tracking branch 'origin/dev' into eth-maker-tpu-v2
laruh Nov 5, 2024
ed02392
review: update payment state index consts names
laruh Nov 5, 2024
1301084
review: remove redundant validation
laruh Nov 7, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions mm2src/coins/coin_errors.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::eth::eth_swap_v2::{PaymentStatusErr, ValidatePaymentV2Err};
use crate::eth::nft_swap_v2::errors::{Erc721FunctionError, HtlcParamsError, PrepareTxDataError};
use crate::eth::eth_swap_v2::{PaymentStatusErr, PrepareTxDataError, ValidatePaymentV2Err};
use crate::eth::nft_swap_v2::errors::{Erc721FunctionError, HtlcParamsError};
use crate::eth::{EthAssocTypesError, EthNftAssocTypesError, Web3RpcError};
use crate::{utxo::rpc_clients::UtxoRpcError, NumConversError, UnexpectedDerivationMethod};
use enum_derives::EnumFromStringify;
Expand All @@ -24,7 +24,8 @@ pub enum ValidatePaymentError {
"NumConversError",
"UnexpectedDerivationMethod",
"keys::Error",
"PrepareTxDataError"
"PrepareTxDataError",
"ethabi::Error"
)]
InternalError(String),
/// Problem with deserializing the transaction, or one of the transaction parts is invalid.
Expand All @@ -49,8 +50,7 @@ pub enum ValidatePaymentError {
WatcherRewardError(String),
/// Input payment timelock overflows the type used by specific coin.
TimelockOverflow(TryFromIntError),
#[display(fmt = "Nft Protocol is not supported yet!")]
NftProtocolNotSupported,
ProtocolNotSupported(String),
InvalidData(String),
}

Expand All @@ -77,7 +77,9 @@ impl From<Web3RpcError> for ValidatePaymentError {
| Web3RpcError::Timeout(internal)
| Web3RpcError::NumConversError(internal)
| Web3RpcError::InvalidGasApiConfig(internal) => ValidatePaymentError::InternalError(internal),
Web3RpcError::NftProtocolNotSupported => ValidatePaymentError::NftProtocolNotSupported,
Web3RpcError::NftProtocolNotSupported => {
ValidatePaymentError::ProtocolNotSupported("Nft protocol is not supported".to_string())
},
}
}
}
Expand Down
228 changes: 216 additions & 12 deletions mm2src/coins/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,12 +245,51 @@ pub mod gas_limit {
pub const ERC20_RECEIVER_SPEND: u64 = 150_000;
/// Gas limit for swap refund tx with coins
pub const ETH_SENDER_REFUND: u64 = 100_000;
/// Gas limit for swap refund tx with with ERC20 tokens
/// Gas limit for swap refund tx with ERC20 tokens
pub const ERC20_SENDER_REFUND: u64 = 150_000;
/// Gas limit for other operations
pub const ETH_MAX_TRADE_GAS: u64 = 150_000;
}

/// Default gas limits for EthGasLimitV2
pub mod gas_limit_v2 {
/// Gas limits for maker operations in EtomicSwapMakerV2 contract
pub mod maker {
pub const ETH_PAYMENT: u64 = 65_000;
pub const ERC20_PAYMENT: u64 = 115_000;
shamardy marked this conversation as resolved.
Show resolved Hide resolved
pub const ETH_TAKER_SPEND: u64 = 65_000;
pub const ERC20_TAKER_SPEND: u64 = 65_000;
pub const ETH_MAKER_REFUND_TIMELOCK: u64 = 65_000;
pub const ERC20_MAKER_REFUND_TIMELOCK: u64 = 65_000;
pub const ETH_MAKER_REFUND_SECRET: u64 = 65_000;
pub const ERC20_MAKER_REFUND_SECRET: u64 = 65_000;
}

/// Gas limits for taker operations in EtomicSwapTakerV2 contract
pub mod taker {
pub const ETH_PAYMENT: u64 = 65_000;
pub const ERC20_PAYMENT: u64 = 115_000;
pub const ETH_MAKER_SPEND: u64 = 100_000;
pub const ERC20_MAKER_SPEND: u64 = 115_000;
pub const ETH_TAKER_REFUND_TIMELOCK: u64 = 65_000;
pub const ERC20_TAKER_REFUND_TIMELOCK: u64 = 70_000;
pub const ETH_TAKER_REFUND_SECRET: u64 = 65_000;
pub const ERC20_TAKER_REFUND_SECRET: u64 = 70_000;
pub const APPROVE_PAYMENT: u64 = 50_000;
}

pub mod nft_maker {
pub const ERC721_PAYMENT: u64 = 130_000;
pub const ERC1155_PAYMENT: u64 = 130_000;
pub const ERC721_TAKER_SPEND: u64 = 100_000;
pub const ERC1155_TAKER_SPEND: u64 = 100_000;
pub const ERC721_MAKER_REFUND_TIMELOCK: u64 = 100_000;
pub const ERC1155_MAKER_REFUND_TIMELOCK: u64 = 100_000;
pub const ERC721_MAKER_REFUND_SECRET: u64 = 100_000;
pub const ERC1155_MAKER_REFUND_SECRET: u64 = 100_000;
}
}

borngraced marked this conversation as resolved.
Show resolved Hide resolved
/// Coin conf param to override default gas limits
#[derive(Deserialize)]
#[serde(default)]
Expand All @@ -269,7 +308,7 @@ pub struct EthGasLimit {
pub erc20_receiver_spend: u64,
/// Gas limit for swap refund tx with coins
pub eth_sender_refund: u64,
/// Gas limit for swap refund tx with with ERC20 tokens
/// Gas limit for swap refund tx with ERC20 tokens
pub erc20_sender_refund: u64,
/// Gas limit for other operations
pub eth_max_trade_gas: u64,
Expand All @@ -291,6 +330,112 @@ impl Default for EthGasLimit {
}
}

#[derive(Default, Deserialize)]
#[serde(default)]
pub struct EthGasLimitV2 {
pub maker: MakerGasLimitV2,
pub taker: TakerGasLimitV2,
pub nft_maker: NftMakerGasLimitV2,
}

#[derive(Deserialize)]
#[serde(default)]
pub struct MakerGasLimitV2 {
pub eth_payment: u64,
pub erc20_payment: u64,
pub eth_taker_spend: u64,
pub erc20_taker_spend: u64,
pub eth_maker_refund_timelock: u64,
pub erc20_maker_refund_timelock: u64,
pub eth_maker_refund_secret: u64,
pub erc20_maker_refund_secret: u64,
}

#[derive(Deserialize)]
#[serde(default)]
pub struct TakerGasLimitV2 {
pub eth_payment: u64,
pub erc20_payment: u64,
pub eth_maker_spend: u64,
pub erc20_maker_spend: u64,
pub eth_taker_refund_timelock: u64,
pub erc20_taker_refund_timelock: u64,
pub eth_taker_refund_secret: u64,
pub erc20_taker_refund_secret: u64,
pub approve_payment: u64,
}

#[derive(Deserialize)]
#[serde(default)]
pub struct NftMakerGasLimitV2 {
pub erc721_payment: u64,
pub erc1155_payment: u64,
pub erc721_taker_spend: u64,
pub erc1155_taker_spend: u64,
pub erc721_maker_refund_timelock: u64,
pub erc1155_maker_refund_timelock: u64,
pub erc721_maker_refund_secret: u64,
pub erc1155_maker_refund_secret: u64,
}

impl Default for MakerGasLimitV2 {
fn default() -> Self {
MakerGasLimitV2 {
eth_payment: gas_limit_v2::maker::ETH_PAYMENT,
erc20_payment: gas_limit_v2::maker::ERC20_PAYMENT,
eth_taker_spend: gas_limit_v2::maker::ETH_TAKER_SPEND,
erc20_taker_spend: gas_limit_v2::maker::ERC20_TAKER_SPEND,
eth_maker_refund_timelock: gas_limit_v2::maker::ETH_MAKER_REFUND_TIMELOCK,
erc20_maker_refund_timelock: gas_limit_v2::maker::ERC20_MAKER_REFUND_TIMELOCK,
eth_maker_refund_secret: gas_limit_v2::maker::ETH_MAKER_REFUND_SECRET,
erc20_maker_refund_secret: gas_limit_v2::maker::ERC20_MAKER_REFUND_SECRET,
}
}
}

impl Default for TakerGasLimitV2 {
fn default() -> Self {
TakerGasLimitV2 {
eth_payment: gas_limit_v2::taker::ETH_PAYMENT,
erc20_payment: gas_limit_v2::taker::ERC20_PAYMENT,
eth_maker_spend: gas_limit_v2::taker::ETH_MAKER_SPEND,
erc20_maker_spend: gas_limit_v2::taker::ERC20_MAKER_SPEND,
eth_taker_refund_timelock: gas_limit_v2::taker::ETH_TAKER_REFUND_TIMELOCK,
erc20_taker_refund_timelock: gas_limit_v2::taker::ERC20_TAKER_REFUND_TIMELOCK,
eth_taker_refund_secret: gas_limit_v2::taker::ETH_TAKER_REFUND_SECRET,
erc20_taker_refund_secret: gas_limit_v2::taker::ERC20_TAKER_REFUND_SECRET,
approve_payment: gas_limit_v2::taker::APPROVE_PAYMENT,
}
}
}

impl Default for NftMakerGasLimitV2 {
fn default() -> Self {
NftMakerGasLimitV2 {
erc721_payment: gas_limit_v2::nft_maker::ERC721_PAYMENT,
erc1155_payment: gas_limit_v2::nft_maker::ERC1155_PAYMENT,
erc721_taker_spend: gas_limit_v2::nft_maker::ERC721_TAKER_SPEND,
erc1155_taker_spend: gas_limit_v2::nft_maker::ERC1155_TAKER_SPEND,
erc721_maker_refund_timelock: gas_limit_v2::nft_maker::ERC721_MAKER_REFUND_TIMELOCK,
erc1155_maker_refund_timelock: gas_limit_v2::nft_maker::ERC1155_MAKER_REFUND_TIMELOCK,
erc721_maker_refund_secret: gas_limit_v2::nft_maker::ERC721_MAKER_REFUND_SECRET,
erc1155_maker_refund_secret: gas_limit_v2::nft_maker::ERC1155_MAKER_REFUND_SECRET,
}
}
}

trait ExtractGasLimit: Default + for<'de> Deserialize<'de> {
fn key() -> &'static str;
}

impl ExtractGasLimit for EthGasLimit {
fn key() -> &'static str { "gas_limit" }
}

impl ExtractGasLimit for EthGasLimitV2 {
fn key() -> &'static str { "gas_limit_v2" }
}

/// Max transaction type according to EIP-2718
const ETH_MAX_TX_TYPE: u64 = 0x7f;

Expand Down Expand Up @@ -681,6 +826,7 @@ pub struct EthCoinImpl {
pub(crate) platform_fee_estimator_state: Arc<FeeEstimatorState>,
/// Config provided gas limits for swap and send transactions
pub(crate) gas_limit: EthGasLimit,
pub(crate) gas_limit_v2: EthGasLimitV2,
/// This spawner is used to spawn coin's related futures that should be aborted on coin deactivation
/// and on [`MmArc::stop`].
pub abortable_system: AbortableQueue,
Expand Down Expand Up @@ -1759,7 +1905,11 @@ impl WatcherOps for EthCoin {
)));
}
},
EthCoinType::Nft { .. } => return MmError::err(ValidatePaymentError::NftProtocolNotSupported),
EthCoinType::Nft { .. } => {
return MmError::err(ValidatePaymentError::ProtocolNotSupported(
"Nft protocol is not supported by watchers yet".to_string(),
))
},
}

Ok(())
Expand Down Expand Up @@ -2000,7 +2150,11 @@ impl WatcherOps for EthCoin {
)));
}
},
EthCoinType::Nft { .. } => return MmError::err(ValidatePaymentError::NftProtocolNotSupported),
EthCoinType::Nft { .. } => {
return MmError::err(ValidatePaymentError::ProtocolNotSupported(
"Nft protocol is not supported by watchers yet".to_string(),
))
},
}

Ok(())
Expand Down Expand Up @@ -4612,7 +4766,7 @@ impl EthCoin {
EthCoinType::Erc20 { token_addr, .. } => token_addr,
EthCoinType::Nft { .. } => {
return Err(TransactionErr::ProtocolNotSupported(ERRL!(
"Nft Protocol is not supported yet!"
"Nft Protocol is not supported by 'approve'!"
)))
},
};
Expand Down Expand Up @@ -4952,7 +5106,11 @@ impl EthCoin {
)));
}
},
EthCoinType::Nft { .. } => return MmError::err(ValidatePaymentError::NftProtocolNotSupported),
EthCoinType::Nft { .. } => {
return MmError::err(ValidatePaymentError::ProtocolNotSupported(
"Nft protocol is not supported by legacy swap".to_string(),
))
},
}

Ok(())
Expand Down Expand Up @@ -5890,7 +6048,11 @@ fn validate_fee_impl(coin: EthCoin, validate_fee_args: EthValidateFeeArgs<'_>) -
},
}
},
EthCoinType::Nft { .. } => return MmError::err(ValidatePaymentError::NftProtocolNotSupported),
EthCoinType::Nft { .. } => {
return MmError::err(ValidatePaymentError::ProtocolNotSupported(
"Nft protocol is not supported".to_string(),
))
},
}

Ok(())
Expand Down Expand Up @@ -6370,7 +6532,8 @@ pub async fn eth_coin_from_conf_and_request(

let platform_fee_estimator_state = FeeEstimatorState::init_fee_estimator(ctx, conf, &coin_type).await?;
let max_eth_tx_type = get_max_eth_tx_type_conf(ctx, conf, &coin_type).await?;
let gas_limit = extract_gas_limit_from_conf(conf)?;
let gas_limit: EthGasLimit = extract_gas_limit_from_conf(conf)?;
let gas_limit_v2: EthGasLimitV2 = extract_gas_limit_from_conf(conf)?;

let coin = EthCoinImpl {
priv_key_policy: key_pair,
Expand All @@ -6397,6 +6560,7 @@ pub async fn eth_coin_from_conf_and_request(
nfts_infos: Default::default(),
platform_fee_estimator_state,
gas_limit,
gas_limit_v2,
abortable_system,
};

Expand Down Expand Up @@ -7022,11 +7186,12 @@ pub fn pubkey_from_extended(extended_pubkey: &Secp256k1ExtendedPublicKey) -> Pub
pubkey_uncompressed
}

fn extract_gas_limit_from_conf(coin_conf: &Json) -> Result<EthGasLimit, String> {
if coin_conf["gas_limit"].is_null() {
fn extract_gas_limit_from_conf<T: ExtractGasLimit>(coin_conf: &Json) -> Result<T, String> {
let key = T::key();
if coin_conf[key].is_null() {
Ok(Default::default())
} else {
json::from_value(coin_conf["gas_limit"].clone()).map_err(|e| e.to_string())
json::from_value(coin_conf[key].clone()).map_err(|e| e.to_string())
borngraced marked this conversation as resolved.
Show resolved Hide resolved
}
}

Expand Down Expand Up @@ -7150,7 +7315,7 @@ impl TakerCoinSwapOpsV2 for EthCoin {
taker_payment: &Self::Tx,
_from_block: u64,
wait_until: u64,
) -> MmResult<Self::Tx, WaitForTakerPaymentSpendError> {
) -> MmResult<Self::Tx, WaitForPaymentSpendError> {
self.wait_for_taker_payment_spend_impl(taker_payment, wait_until).await
}
}
Expand Down Expand Up @@ -7213,8 +7378,47 @@ impl EthCoin {
nfts_infos: Arc::clone(&self.nfts_infos),
platform_fee_estimator_state: Arc::clone(&self.platform_fee_estimator_state),
gas_limit: EthGasLimit::default(),
gas_limit_v2: EthGasLimitV2::default(),
abortable_system: self.abortable_system.create_subsystem().unwrap(),
};
EthCoin(Arc::new(coin))
}
}

#[async_trait]
impl MakerCoinSwapOpsV2 for EthCoin {
async fn send_maker_payment_v2(&self, args: SendMakerPaymentArgs<'_, Self>) -> Result<Self::Tx, TransactionErr> {
self.send_maker_payment_v2_impl(args).await
}

async fn validate_maker_payment_v2(&self, args: ValidateMakerPaymentArgs<'_, Self>) -> ValidatePaymentResult<()> {
self.validate_maker_payment_v2_impl(args).await
}

async fn refund_maker_payment_v2_timelock(
&self,
args: RefundMakerPaymentTimelockArgs<'_>,
) -> Result<Self::Tx, TransactionErr> {
self.refund_maker_payment_v2_timelock_impl(args).await
}

async fn refund_maker_payment_v2_secret(
&self,
args: RefundMakerPaymentSecretArgs<'_, Self>,
) -> Result<Self::Tx, TransactionErr> {
self.refund_maker_payment_v2_secret_impl(args).await
}

async fn spend_maker_payment_v2(&self, args: SpendMakerPaymentArgs<'_, Self>) -> Result<Self::Tx, TransactionErr> {
self.spend_maker_payment_v2_impl(args).await
}

async fn wait_for_maker_payment_spend(
&self,
maker_payment: &Self::Tx,
_from_block: u64,
wait_until: u64,
) -> MmResult<Self::Tx, WaitForPaymentSpendError> {
self.wait_for_maker_payment_spend_impl(maker_payment, wait_until).await
}
}
Loading
Loading