diff --git a/mm2src/coins/eth/swap_contract_abi.json b/mm2src/coins/eth/swap_contract_abi.json index 79cd76e233..28e1cf8ada 100644 --- a/mm2src/coins/eth/swap_contract_abi.json +++ b/mm2src/coins/eth/swap_contract_abi.json @@ -1,415 +1,224 @@ [ - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "PaymentSent", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "secret", - "type": "bytes32" - } - ], - "name": "ReceiverSpent", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "SenderRefunded", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_id", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_tokenAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "_receiver", - "type": "address" - }, - { - "internalType": "bytes20", - "name": "_secretHash", - "type": "bytes20" - }, - { - "internalType": "uint64", - "name": "_lockTime", - "type": "uint64" - } - ], - "name": "erc20Payment", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_id", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_tokenAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "_receiver", - "type": "address" - }, - { - "internalType": "bytes20", - "name": "_secretHash", - "type": "bytes20" - }, - { - "internalType": "uint64", - "name": "_lockTime", - "type": "uint64" - }, - { - "internalType": "enum EtomicSwap.RewardTargetOnSpend", - "name": "_rewardTarget", - "type": "uint8" - }, - { - "internalType": "bool", - "name": "_sendsContractRewardOnSpend", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "_rewardAmount", - "type": "uint256" - } - ], - "name": "erc20PaymentReward", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_id", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "_receiver", - "type": "address" - }, - { - "internalType": "bytes20", - "name": "_secretHash", - "type": "bytes20" - }, - { - "internalType": "uint64", - "name": "_lockTime", - "type": "uint64" - } - ], - "name": "ethPayment", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_id", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "_receiver", - "type": "address" - }, - { - "internalType": "bytes20", - "name": "_secretHash", - "type": "bytes20" - }, - { - "internalType": "uint64", - "name": "_lockTime", - "type": "uint64" - }, - { - "internalType": "enum EtomicSwap.RewardTargetOnSpend", - "name": "_rewardTarget", - "type": "uint8" - }, - { - "internalType": "bool", - "name": "_sendsContractRewardOnSpend", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "_rewardAmount", - "type": "uint256" - } - ], - "name": "ethPaymentReward", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_id", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "_secret", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "_tokenAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "_sender", - "type": "address" - } - ], - "name": "receiverSpend", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_id", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "_secret", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "_tokenAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "_sender", - "type": "address" - }, - { - "internalType": "address", - "name": "_receiver", - "type": "address" - }, - { - "internalType": "enum EtomicSwap.RewardTargetOnSpend", - "name": "_rewardTarget", - "type": "uint8" - }, - { - "internalType": "bool", - "name": "_sendsContractRewardOnSpend", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "_rewardAmount", - "type": "uint256" - } - ], - "name": "receiverSpendReward", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_id", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "bytes20", - "name": "_paymentHash", - "type": "bytes20" - }, - { - "internalType": "address", - "name": "_tokenAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "_receiver", - "type": "address" - } - ], - "name": "senderRefund", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_id", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "bytes20", - "name": "_paymentHash", - "type": "bytes20" - }, - { - "internalType": "address", - "name": "_tokenAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "_sender", - "type": "address" - }, - { - "internalType": "address", - "name": "_receiver", - "type": "address" - }, - { - "internalType": "enum EtomicSwap.RewardTargetOnSpend", - "name": "_rewardTarget", - "type": "uint8" - }, - { - "internalType": "bool", - "name": "_sendsReward", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "_rewardAmount", - "type": "uint256" - } - ], - "name": "senderRefundReward", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "payments", - "outputs": [ - { - "internalType": "bytes20", - "name": "paymentHash", - "type": "bytes20" - }, - { - "internalType": "uint64", - "name": "lockTime", - "type": "uint64" - }, - { - "internalType": "enum EtomicSwap.PaymentState", - "name": "state", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - } -] \ No newline at end of file + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "SafeERC20FailedOperation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "PaymentSent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "secret", + "type": "bytes32" + } + ], + "name": "ReceiverSpent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "SenderRefunded", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "bytes20", + "name": "secretHash", + "type": "bytes20" + }, + { + "internalType": "uint64", + "name": "lockTime", + "type": "uint64" + } + ], + "name": "erc20Payment", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "bytes20", + "name": "secretHash", + "type": "bytes20" + }, + { + "internalType": "uint64", + "name": "lockTime", + "type": "uint64" + } + ], + "name": "ethPayment", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "payments", + "outputs": [ + { + "internalType": "bytes20", + "name": "paymentHash", + "type": "bytes20" + }, + { + "internalType": "uint64", + "name": "lockTime", + "type": "uint64" + }, + { + "internalType": "enum EtomicSwap.PaymentState", + "name": "state", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "secret", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "receiverSpend", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes20", + "name": "secretHash", + "type": "bytes20" + }, + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "senderRefund", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/mm2src/derives/enum_derives/src/lib.rs b/mm2src/derives/enum_derives/src/lib.rs index 18d55e912a..854030a732 100644 --- a/mm2src/derives/enum_derives/src/lib.rs +++ b/mm2src/derives/enum_derives/src/lib.rs @@ -144,7 +144,6 @@ pub fn derive(input: TokenStream) -> TokenStream { /// Polygon, /// } /// -///#[test] ///fn test_enum_variant_list() { /// let all_chains = Chain::variant_list(); /// assert_eq!(all_chains, vec![ diff --git a/mm2src/mm2_main/tests/docker_tests/eth_docker_tests.rs b/mm2src/mm2_main/tests/docker_tests/eth_docker_tests.rs index fd82a5e70b..47e2db3f5e 100644 --- a/mm2src/mm2_main/tests/docker_tests/eth_docker_tests.rs +++ b/mm2src/mm2_main/tests/docker_tests/eth_docker_tests.rs @@ -2,11 +2,13 @@ use super::helpers::env::random_secp256k1_secret; use super::helpers::eth::{ erc20_coin_with_random_privkey, erc20_contract, erc20_contract_checksum, eth_coin_with_random_privkey, eth_coin_with_random_privkey_using_urls, fill_erc20, fill_eth, geth_account, geth_erc1155_contract, - geth_erc721_contract, geth_maker_swap_v2, geth_nft_maker_swap_v2, geth_taker_swap_v2, swap_contract, - swap_contract_checksum, GETH_DEV_CHAIN_ID, GETH_NONCE_LOCK, GETH_RPC_URL, GETH_WEB3, MM_CTX, MM_CTX1, + geth_erc721_contract, geth_maker_swap_v2, geth_nft_maker_swap_v2, geth_taker_swap_v2, geth_usdt_contract, + swap_contract, swap_contract_checksum, usdt_coin_with_random_privkey, GETH_DEV_CHAIN_ID, GETH_NONCE_LOCK, + GETH_RPC_URL, GETH_WEB3, MM_CTX, MM_CTX1, }; use crate::common::Future01CompatExt; use bitcrypto::{dhash160, sha256}; +use coins::eth::erc20::get_erc20_token_info; use coins::eth::gas_limit::ETH_MAX_TRADE_GAS; use coins::eth::v2_activation::{eth_coin_from_conf_and_request_v2, EthActivationV2Request, EthNode}; use coins::eth::{ @@ -2759,3 +2761,208 @@ fn verify_locked_amount(mm: &MarketMakerIt, role: &str, coin: &str) { log!("{} {} locked amount: {:?}", role, coin, locked.locked_amount); assert_eq!(locked.coin, coin); } + +// ================================ +// USDT (Non-Standard ERC20) Tests +// ================================ +// These tests verify that SafeERC20 in the V1 EtomicSwap contract +// correctly handles USDT's non-standard transfer/transferFrom functions +// which don't return a boolean value. + +fn send_and_spend_usdt_maker_payment_impl(swap_txfee_policy: SwapGasFeePolicy) { + thread::sleep(Duration::from_secs(7)); + let maker_usdt_coin = usdt_coin_with_random_privkey(swap_contract()); + let taker_usdt_coin = usdt_coin_with_random_privkey(swap_contract()); + + assert!(block_on(maker_usdt_coin.set_swap_gas_fee_policy(swap_txfee_policy.clone())).is_ok()); + assert!(block_on(taker_usdt_coin.set_swap_gas_fee_policy(swap_txfee_policy)).is_ok()); + + let time_lock = now_sec() + 1000; + let maker_pubkey = maker_usdt_coin.derive_htlc_pubkey(&[]); + let taker_pubkey = taker_usdt_coin.derive_htlc_pubkey(&[]); + let secret = &[2; 32]; + let secret_hash_owned = dhash160(secret); + let secret_hash = secret_hash_owned.as_slice(); + + let send_payment_args = SendPaymentArgs { + time_lock_duration: 1000, + time_lock, + other_pubkey: &taker_pubkey, + secret_hash, + amount: BigDecimal::from_str("10").unwrap(), + swap_contract_address: &Some(swap_contract().as_bytes().into()), + swap_unique_data: &[], + payment_instructions: &None, + watcher_reward: None, + wait_for_confirmation_until: now_sec() + 60, + }; + let usdt_maker_payment = block_on(maker_usdt_coin.send_maker_payment(send_payment_args)).unwrap(); + log!( + "USDT maker payment tx hash {:02x}", + usdt_maker_payment.tx_hash_as_bytes() + ); + + let confirm_input = ConfirmPaymentInput { + payment_tx: usdt_maker_payment.tx_hex(), + confirmations: 1, + requires_nota: false, + wait_until: now_sec() + 60, + check_every: 1, + }; + block_on_f01(taker_usdt_coin.wait_for_confirmations(confirm_input)).unwrap(); + + let spend_args = SpendPaymentArgs { + other_payment_tx: &usdt_maker_payment.tx_hex(), + time_lock, + other_pubkey: &maker_pubkey, + secret, + secret_hash, + swap_contract_address: &Some(swap_contract().as_bytes().into()), + swap_unique_data: &[], + watcher_reward: false, + }; + let payment_spend = block_on(taker_usdt_coin.send_taker_spends_maker_payment(spend_args)).unwrap(); + log!("USDT payment spend tx hash {:02x}", payment_spend.tx_hash_as_bytes()); + + let confirm_input = ConfirmPaymentInput { + payment_tx: payment_spend.tx_hex(), + confirmations: 1, + requires_nota: false, + wait_until: now_sec() + 60, + check_every: 1, + }; + block_on_f01(taker_usdt_coin.wait_for_confirmations(confirm_input)).unwrap(); + + let search_input = SearchForSwapTxSpendInput { + time_lock, + other_pub: &taker_pubkey, + secret_hash, + tx: &usdt_maker_payment.tx_hex(), + search_from_block: 0, + swap_contract_address: &Some(swap_contract().as_bytes().into()), + swap_unique_data: &[], + }; + let search_tx = block_on(maker_usdt_coin.search_for_swap_tx_spend_my(search_input)) + .unwrap() + .unwrap(); + + let expected = FoundSwapTxSpend::Spent(payment_spend); + assert_eq!(expected, search_tx); +} + +#[test] +fn send_and_spend_usdt_maker_payment_legacy_gas_policy() { + send_and_spend_usdt_maker_payment_impl(SwapGasFeePolicy::Legacy); +} + +#[test] +fn send_and_spend_usdt_maker_payment_priority_fee() { + send_and_spend_usdt_maker_payment_impl(SwapGasFeePolicy::Medium); +} + +fn send_and_refund_usdt_maker_payment_impl(swap_txfee_policy: SwapGasFeePolicy) { + thread::sleep(Duration::from_secs(10)); + let usdt_coin = usdt_coin_with_random_privkey(swap_contract()); + assert!(block_on(usdt_coin.set_swap_gas_fee_policy(swap_txfee_policy)).is_ok()); + + // Use a past time_lock to allow immediate refund + let time_lock = now_sec() - 100; + let other_pubkey = &[ + 0x02, 0xc6, 0x6e, 0x7d, 0x89, 0x66, 0xb5, 0xc5, 0x55, 0xaf, 0x58, 0x05, 0x98, 0x9d, 0xa9, 0xfb, 0xf8, 0xdb, + 0x95, 0xe1, 0x56, 0x31, 0xce, 0x35, 0x8c, 0x3a, 0x17, 0x10, 0xc9, 0x62, 0x67, 0x90, 0x63, + ]; + let secret_hash = &[1; 20]; + + let send_payment_args = SendPaymentArgs { + time_lock_duration: 100, + time_lock, + other_pubkey, + secret_hash, + amount: BigDecimal::from_str("10").unwrap(), // 10 USDT + swap_contract_address: &Some(swap_contract().as_bytes().into()), + swap_unique_data: &[], + payment_instructions: &None, + watcher_reward: None, + wait_for_confirmation_until: now_sec() + 60, + }; + let usdt_maker_payment = block_on(usdt_coin.send_maker_payment(send_payment_args)).unwrap(); + log!( + "USDT maker payment tx hash {:02x}", + usdt_maker_payment.tx_hash_as_bytes() + ); + + let confirm_input = ConfirmPaymentInput { + payment_tx: usdt_maker_payment.tx_hex(), + confirmations: 1, + requires_nota: false, + wait_until: now_sec() + 60, + check_every: 1, + }; + block_on_f01(usdt_coin.wait_for_confirmations(confirm_input)).unwrap(); + + let refund_args = RefundPaymentArgs { + payment_tx: &usdt_maker_payment.tx_hex(), + time_lock, + other_pubkey, + tx_type_with_secret_hash: SwapTxTypeWithSecretHash::TakerOrMakerPayment { + maker_secret_hash: secret_hash, + }, + swap_contract_address: &Some(swap_contract().as_bytes().into()), + swap_unique_data: &[], + watcher_reward: false, + }; + let payment_refund = block_on(usdt_coin.send_maker_refunds_payment(refund_args)).unwrap(); + log!("USDT payment refund tx hash {:02x}", payment_refund.tx_hash_as_bytes()); + + let confirm_input = ConfirmPaymentInput { + payment_tx: payment_refund.tx_hex(), + confirmations: 1, + requires_nota: false, + wait_until: now_sec() + 60, + check_every: 1, + }; + block_on_f01(usdt_coin.wait_for_confirmations(confirm_input)).unwrap(); + + let search_input = SearchForSwapTxSpendInput { + time_lock, + other_pub: other_pubkey, + secret_hash, + tx: &usdt_maker_payment.tx_hex(), + search_from_block: 0, + swap_contract_address: &Some(swap_contract().as_bytes().into()), + swap_unique_data: &[], + }; + let search_tx = block_on(usdt_coin.search_for_swap_tx_spend_my(search_input)) + .unwrap() + .unwrap(); + + let expected = FoundSwapTxSpend::Refunded(payment_refund); + assert_eq!(expected, search_tx); +} + +#[test] +fn send_and_refund_usdt_maker_payment_legacy_gas_policy() { + send_and_refund_usdt_maker_payment_impl(SwapGasFeePolicy::Legacy); +} + +#[test] +fn send_and_refund_usdt_maker_payment_priority_fee() { + send_and_refund_usdt_maker_payment_impl(SwapGasFeePolicy::Medium); +} + +/// Test that get_erc20_token_info correctly fetches USDT token info from chain, +/// verifying that the non-standard decimals() return type (uint256 instead of uint8) is handled. +/// This is critical because USDT's decimals() returns uint256, not the standard uint8. +#[test] +fn test_usdt_get_token_info() { + // Use ETH coin as web3 provider to query the USDT contract + let eth_coin = eth_coin_with_random_privkey(swap_contract()); + let usdt_address = geth_usdt_contract(); + + // Call get_erc20_token_info which internally calls decimals() on the contract + // This verifies that the uint256 return type from USDT's decimals() is correctly parsed + let token_info = block_on(get_erc20_token_info(ð_coin, usdt_address)).unwrap(); + + assert_eq!(token_info.symbol, "USDT"); + assert_eq!(token_info.decimals, 6); +} diff --git a/mm2src/mm2_main/tests/docker_tests/helpers/eth.rs b/mm2src/mm2_main/tests/docker_tests/helpers/eth.rs index b80ffbbea7..f7ef7d611e 100644 --- a/mm2src/mm2_main/tests/docker_tests/helpers/eth.rs +++ b/mm2src/mm2_main/tests/docker_tests/helpers/eth.rs @@ -25,7 +25,7 @@ use crypto::Secp256k1Secret; use ethabi::Token; use ethereum_types::{H160 as H160Eth, U256}; use mm2_core::mm_ctx::{MmArc, MmCtxBuilder}; -use mm2_test_helpers::for_tests::{erc20_dev_conf, eth_dev_conf}; +use mm2_test_helpers::for_tests::{erc20_dev_conf, eth_dev_conf, usdt_dev_conf}; use mm2_test_helpers::get_passphrase; use serde_json::json; use std::sync::{Mutex, OnceLock}; @@ -85,6 +85,8 @@ static GETH_ERC721_CONTRACT: OnceLock = OnceLock::new(); static GETH_ERC1155_CONTRACT: OnceLock = OnceLock::new(); /// NFT Maker Swap V2 contract address on Geth dev node static GETH_NFT_MAKER_SWAP_V2: OnceLock = OnceLock::new(); +/// USDT contract address on Geth dev node (non-standard ERC20 for SafeERC20 testing) +static GETH_USDT_CONTRACT: OnceLock = OnceLock::new(); /// Geth RPC URL pub static GETH_RPC_URL: &str = "http://127.0.0.1:8545"; @@ -119,6 +121,11 @@ pub const NFT_MAKER_SWAP_V2_BYTES: &str = pub const MAKER_SWAP_V2_BYTES: &str = include_str!("../../../../mm2_test_helpers/contract_bytes/maker_swap_v2_bytes"); /// https://github.com/KomodoPlatform/etomic-swap/blob/7d4eafd4a408188a95aee78a41f0bf5f9116ffa2/contracts/EtomicSwapTakerV2.sol pub const TAKER_SWAP_V2_BYTES: &str = include_str!("../../../../mm2_test_helpers/contract_bytes/taker_swap_v2_bytes"); +/// Real USDT mainnet contract bytecode from Etherscan for SafeERC20 testing. +/// This is a non-standard ERC20 where transfer/transferFrom return void instead of bool. +pub const USDT_CONTRACT_BYTES: &str = include_str!("../../../../mm2_test_helpers/contract_bytes/usdt_contract_bytes"); +/// USDT ABI from Etherscan - note the non-standard outputs:[] for transfer/transferFrom +pub const USDT_ABI: &str = include_str!("../../../../mm2_test_helpers/dummy_files/usdt_abi.json"); /// Geth dev chain ID used for testing pub const GETH_DEV_CHAIN_ID: u64 = 1337; @@ -199,11 +206,25 @@ pub fn geth_nft_maker_swap_v2() -> Address { .expect("GETH_NFT_MAKER_SWAP_V2 not initialized - call init_geth_node() first") } +/// Get the USDT contract address. +/// Panics if called before `init_geth_node()`. +pub fn geth_usdt_contract() -> Address { + *GETH_USDT_CONTRACT + .get() + .expect("GETH_USDT_CONTRACT not initialized - call init_geth_node() first") +} + /// Return ERC20 dev token contract address in checksum format pub fn erc20_contract_checksum() -> String { checksum_address(&format!("{:02x}", erc20_contract())) } +/// Return USDT contract address in checksum format +#[cfg(any(feature = "docker-tests-eth", feature = "docker-tests-watchers-eth"))] +pub fn usdt_contract_checksum() -> String { + checksum_address(&format!("{:02x}", geth_usdt_contract())) +} + /// Return swap contract address in checksum format (with 0x prefix) #[cfg(any( feature = "docker-tests-eth", @@ -319,6 +340,22 @@ pub fn fill_erc20(to_addr: Address, amount: U256) { wait_for_confirmation(tx_hash); } +/// Fill an address with USDT tokens from the Geth coinbase account. +/// Note: USDT's transfer() doesn't return a value, so we use the USDT ABI. +pub fn fill_usdt(to_addr: Address, amount: U256) { + let _guard = GETH_NONCE_LOCK.lock().unwrap(); + let usdt = Contract::from_json(GETH_WEB3.eth(), geth_usdt_contract(), USDT_ABI.as_bytes()).unwrap(); + + let tx_hash = block_on(usdt.call( + "transfer", + (Token::Address(to_addr), Token::Uint(amount)), + geth_account(), + Options::default(), + )) + .unwrap(); + wait_for_confirmation(tx_hash); +} + // ============================================================================= // Coin creation utilities - create test coins with random keys // Only used by docker-tests-eth and docker-tests-watchers-eth (not integration) @@ -430,6 +467,72 @@ pub fn erc20_coin_with_random_privkey(swap_contract_address: Address) -> EthCoin erc20_coin } +/// Creates USDT protocol coin supplied with 1 ETH and 100 USDT. +/// Uses the real USDT contract (non-standard ERC20) for SafeERC20 testing. +#[cfg(any(feature = "docker-tests-eth", feature = "docker-tests-watchers-eth"))] +pub fn usdt_coin_with_random_privkey(swap_contract_address: Address) -> EthCoin { + let secret = random_secp256k1_secret(); + + // Register platform ETH coin if not already registered by another parallel test, so platform_coin() lookups work. + if block_on(lp_coinfind(&MM_CTX, "ETH")).ok().flatten().is_none() { + let eth_conf = eth_dev_conf(); + let eth_req = json!({ + "method": "enable", + "coin": "ETH", + "swap_contract_address": swap_contract_address, + "urls": [GETH_RPC_URL], + }); + let platform_coin = block_on(eth_coin_from_conf_and_request( + &MM_CTX, + "ETH", + ð_conf, + ð_req, + CoinProtocol::ETH { + chain_id: GETH_DEV_CHAIN_ID, + }, + PrivKeyBuildPolicy::IguanaPrivKey(secret), + )) + .unwrap(); + let coins_ctx = CoinsContext::from_ctx(&MM_CTX).unwrap(); + // Ignore error if another parallel test already registered the platform + let _ = block_on(coins_ctx.add_platform_with_tokens(platform_coin.into(), vec![], None)); + } + + // Now create the USDT token + let usdt_conf = usdt_dev_conf(&usdt_contract_checksum()); + let req = json!({ + "method": "enable", + "coin": "USDT", + "swap_contract_address": swap_contract_address, + "urls": [GETH_RPC_URL], + }); + + let usdt_coin = block_on(eth_coin_from_conf_and_request( + &MM_CTX, + "USDT", + &usdt_conf, + &req, + CoinProtocol::ERC20 { + platform: "ETH".to_string(), + contract_address: usdt_contract_checksum(), + }, + PrivKeyBuildPolicy::IguanaPrivKey(secret), + )) + .unwrap(); + + let my_address = match usdt_coin.derivation_method() { + DerivationMethod::SingleAddress(addr) => addr.inner(), + _ => panic!("Expected single address"), + }; + + // 1 ETH for gas + fill_eth(my_address, U256::from(10).pow(U256::from(18))); + // 100 USDT (6 decimals) + fill_usdt(my_address, U256::from(100_000_000u64)); + + usdt_coin +} + /// Fills the private key's public address with ETH and ERC20 tokens #[cfg(any(feature = "docker-tests-eth", feature = "docker-tests-integration"))] pub fn fill_eth_erc20_with_private_key(priv_key: Secp256k1Secret) { @@ -875,6 +978,47 @@ pub fn init_geth_node() { .set(geth_erc1155_contract) .expect("GETH_ERC1155_CONTRACT already initialized"); + // Deploy USDT contract (non-standard ERC20 for SafeERC20 testing). + // Note: USDT bytecode already includes constructor args for initialSupply=100000 USDT, + // name="Tether USD", symbol="USDT", decimals=6. + let tx_request_deploy_usdt = TransactionRequest { + from: geth_account, + to: None, + // Explicit gas limit for large contract deployment + gas: Some(U256::from(8_000_000u64)), + gas_price: None, + value: None, + data: Some(hex::decode(USDT_CONTRACT_BYTES).unwrap().into()), + nonce: None, + condition: None, + transaction_type: None, + access_list: None, + max_fee_per_gas: None, + max_priority_fee_per_gas: None, + }; + let deploy_usdt_tx_hash = block_on(GETH_WEB3.eth().send_transaction(tx_request_deploy_usdt)).unwrap(); + log!("Sent USDT deploy transaction {:?}", deploy_usdt_tx_hash); + + let geth_usdt_contract = loop { + let deploy_usdt_tx_receipt = match block_on(GETH_WEB3.eth().transaction_receipt(deploy_usdt_tx_hash)) { + Ok(receipt) => receipt, + Err(_) => { + thread::sleep(Duration::from_millis(100)); + continue; + }, + }; + + if let Some(receipt) = deploy_usdt_tx_receipt { + let addr = receipt.contract_address.unwrap(); + log!("GETH_USDT_CONTRACT {:?}", addr); + break addr; + } + thread::sleep(Duration::from_millis(100)); + }; + GETH_USDT_CONTRACT + .set(geth_usdt_contract) + .expect("GETH_USDT_CONTRACT already initialized"); + let alice_passphrase = get_passphrase!(".env.client", "ALICE_PASSPHRASE").unwrap(); let alice_keypair = key_pair_from_seed(&alice_passphrase).unwrap(); let alice_eth_addr = addr_from_raw_pubkey(alice_keypair.public()).unwrap(); diff --git a/mm2src/mm2_main/tests/docker_tests/runner/geth.rs b/mm2src/mm2_main/tests/docker_tests/runner/geth.rs index 0232c65a6c..a87041d554 100644 --- a/mm2src/mm2_main/tests/docker_tests/runner/geth.rs +++ b/mm2src/mm2_main/tests/docker_tests/runner/geth.rs @@ -4,8 +4,8 @@ use super::{DockerTestMode, DockerTestRunner}; use crate::docker_tests::helpers::eth::{ erc20_contract, geth_account, geth_docker_node, geth_erc1155_contract, geth_erc721_contract, geth_maker_swap_v2, - geth_nft_maker_swap_v2, geth_taker_swap_v2, init_geth_node, swap_contract, wait_for_geth_node_ready, - watchers_swap_contract, + geth_nft_maker_swap_v2, geth_taker_swap_v2, geth_usdt_contract, init_geth_node, swap_contract, + wait_for_geth_node_ready, watchers_swap_contract, }; pub(super) fn setup(runner: &mut DockerTestRunner) { @@ -32,4 +32,5 @@ pub(super) fn setup(runner: &mut DockerTestRunner) { let _ = geth_erc721_contract(); let _ = geth_erc1155_contract(); let _ = geth_nft_maker_swap_v2(); + let _ = geth_usdt_contract(); } diff --git a/mm2src/mm2_test_helpers/contract_bytes/swap_contract_bytes b/mm2src/mm2_test_helpers/contract_bytes/swap_contract_bytes index fea8557914..c02d445ddd 100644 --- a/mm2src/mm2_test_helpers/contract_bytes/swap_contract_bytes +++ b/mm2src/mm2_test_helpers/contract_bytes/swap_contract_bytes @@ -1 +1 @@ -608060405234801561001057600080fd5b50611437806100206000396000f3fe60806040526004361061004a5760003560e01c806302ed292b1461004f5780630716326d146100de578063152cf3af1461017b57806346fc0294146101f65780639b415b2a14610294575b600080fd5b34801561005b57600080fd5b506100dc600480360360a081101561007257600080fd5b81019080803590602001909291908035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610339565b005b3480156100ea57600080fd5b506101176004803603602081101561010157600080fd5b8101908080359060200190929190505050610867565b60405180846bffffffffffffffffffffffff19166bffffffffffffffffffffffff191681526020018367ffffffffffffffff1667ffffffffffffffff16815260200182600381111561016557fe5b60ff168152602001935050505060405180910390f35b6101f46004803603608081101561019157600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080356bffffffffffffffffffffffff19169060200190929190803567ffffffffffffffff1690602001909291905050506108bf565b005b34801561020257600080fd5b50610292600480360360a081101561021957600080fd5b81019080803590602001909291908035906020019092919080356bffffffffffffffffffffffff19169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610bd9565b005b610337600480360360c08110156102aa57600080fd5b810190808035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080356bffffffffffffffffffffffff19169060200190929190803567ffffffffffffffff169060200190929190505050610fe2565b005b6001600381111561034657fe5b600080878152602001908152602001600020600001601c9054906101000a900460ff16600381111561037457fe5b1461037e57600080fd5b6000600333836003600288604051602001808281526020019150506040516020818303038152906040526040518082805190602001908083835b602083106103db57805182526020820191506020810190506020830392506103b8565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa15801561041d573d6000803e3d6000fd5b5050506040513d602081101561043257600080fd5b8101908080519060200190929190505050604051602001808281526020019150506040516020818303038152906040526040518082805190602001908083835b602083106104955780518252602082019150602081019050602083039250610472565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa1580156104d7573d6000803e3d6000fd5b5050506040515160601b8689604051602001808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b81526014018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b8152601401846bffffffffffffffffffffffff19166bffffffffffffffffffffffff191681526014018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b8152601401828152602001955050505050506040516020818303038152906040526040518082805190602001908083835b602083106105fc57805182526020820191506020810190506020830392506105d9565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa15801561063e573d6000803e3d6000fd5b5050506040515160601b905060008087815260200190815260200160002060000160009054906101000a900460601b6bffffffffffffffffffffffff1916816bffffffffffffffffffffffff19161461069657600080fd5b6002600080888152602001908152602001600020600001601c6101000a81548160ff021916908360038111156106c857fe5b0217905550600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561074e573373ffffffffffffffffffffffffffffffffffffffff166108fc869081150290604051600060405180830381858888f19350505050158015610748573d6000803e3d6000fd5b50610820565b60008390508073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33886040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1580156107da57600080fd5b505af11580156107ee573d6000803e3d6000fd5b505050506040513d602081101561080457600080fd5b810190808051906020019092919050505061081e57600080fd5b505b7f36c177bcb01c6d568244f05261e2946c8c977fa50822f3fa098c470770ee1f3e8685604051808381526020018281526020019250505060405180910390a1505050505050565b60006020528060005260406000206000915090508060000160009054906101000a900460601b908060000160149054906101000a900467ffffffffffffffff169080600001601c9054906101000a900460ff16905083565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141580156108fc5750600034115b801561094057506000600381111561091057fe5b600080868152602001908152602001600020600001601c9054906101000a900460ff16600381111561093e57fe5b145b61094957600080fd5b60006003843385600034604051602001808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b81526014018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b8152601401846bffffffffffffffffffffffff19166bffffffffffffffffffffffff191681526014018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b8152601401828152602001955050505050506040516020818303038152906040526040518082805190602001908083835b60208310610a6c5780518252602082019150602081019050602083039250610a49565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa158015610aae573d6000803e3d6000fd5b5050506040515160601b90506040518060600160405280826bffffffffffffffffffffffff191681526020018367ffffffffffffffff16815260200160016003811115610af757fe5b81525060008087815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908360601c021790555060208201518160000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550604082015181600001601c6101000a81548160ff02191690836003811115610b9357fe5b02179055509050507fccc9c05183599bd3135da606eaaf535daffe256e9de33c048014cffcccd4ad57856040518082815260200191505060405180910390a15050505050565b60016003811115610be657fe5b600080878152602001908152602001600020600001601c9054906101000a900460ff166003811115610c1457fe5b14610c1e57600080fd5b600060038233868689604051602001808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b81526014018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b8152601401846bffffffffffffffffffffffff19166bffffffffffffffffffffffff191681526014018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b8152601401828152602001955050505050506040516020818303038152906040526040518082805190602001908083835b60208310610d405780518252602082019150602081019050602083039250610d1d565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa158015610d82573d6000803e3d6000fd5b5050506040515160601b905060008087815260200190815260200160002060000160009054906101000a900460601b6bffffffffffffffffffffffff1916816bffffffffffffffffffffffff1916148015610e10575060008087815260200190815260200160002060000160149054906101000a900467ffffffffffffffff1667ffffffffffffffff164210155b610e1957600080fd5b6003600080888152602001908152602001600020600001601c6101000a81548160ff02191690836003811115610e4b57fe5b0217905550600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610ed1573373ffffffffffffffffffffffffffffffffffffffff166108fc869081150290604051600060405180830381858888f19350505050158015610ecb573d6000803e3d6000fd5b50610fa3565b60008390508073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33886040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b158015610f5d57600080fd5b505af1158015610f71573d6000803e3d6000fd5b505050506040513d6020811015610f8757600080fd5b8101908080519060200190929190505050610fa157600080fd5b505b7f1797d500133f8e427eb9da9523aa4a25cb40f50ebc7dbda3c7c81778973f35ba866040518082815260200191505060405180910390a1505050505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415801561101f5750600085115b801561106357506000600381111561103357fe5b600080888152602001908152602001600020600001601c9054906101000a900460ff16600381111561106157fe5b145b61106c57600080fd5b60006003843385888a604051602001808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b81526014018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b8152601401846bffffffffffffffffffffffff19166bffffffffffffffffffffffff191681526014018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b8152601401828152602001955050505050506040516020818303038152906040526040518082805190602001908083835b6020831061118e578051825260208201915060208101905060208303925061116b565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa1580156111d0573d6000803e3d6000fd5b5050506040515160601b90506040518060600160405280826bffffffffffffffffffffffff191681526020018367ffffffffffffffff1681526020016001600381111561121957fe5b81525060008089815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908360601c021790555060208201518160000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550604082015181600001601c6101000a81548160ff021916908360038111156112b557fe5b021790555090505060008590508073ffffffffffffffffffffffffffffffffffffffff166323b872dd33308a6040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050602060405180830381600087803b15801561137d57600080fd5b505af1158015611391573d6000803e3d6000fd5b505050506040513d60208110156113a757600080fd5b81019080805190602001909291905050506113c157600080fd5b7fccc9c05183599bd3135da606eaaf535daffe256e9de33c048014cffcccd4ad57886040518082815260200191505060405180910390a1505050505050505056fea265627a7a723158208c83db436905afce0b7be1012be64818c49323c12d451fe2ab6bce76ff6421c964736f6c63430005110032 \ No newline at end of file +6080604052348015600f57600080fd5b5061135a8061001f6000396000f3fe60806040526004361061005a5760003560e01c8063152cf3af11610043578063152cf3af1461011257806346fc0294146101255780639b415b2a1461014557600080fd5b806302ed292b1461005f5780630716326d14610081575b600080fd5b34801561006b57600080fd5b5061007f61007a3660046110b4565b610165565b005b34801561008d57600080fd5b506100fa61009c366004611104565b600060208190529081526040902054606081901b9074010000000000000000000000000000000000000000810467ffffffffffffffff16907c0100000000000000000000000000000000000000000000000000000000900460ff1683565b6040516101099392919061114c565b60405180910390f35b61007f6101203660046111ec565b6104e9565b34801561013157600080fd5b5061007f610140366004611239565b610836565b34801561015157600080fd5b5061007f610160366004611276565b610b17565b60016000868152602081905260409020547c0100000000000000000000000000000000000000000000000000000000900460ff1660038111156101aa576101aa61111d565b146102225760405162461bcd60e51b815260206004820152602a60248201527f496e76616c6964207061796d656e742073746174652e204d757374206265205060448201527f61796d656e7453656e740000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b600060033383600360028860405160200161023f91815260200190565b60408051601f1981840301815290829052610259916112dc565b602060405180830381855afa158015610276573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610299919061130b565b6040516020016102ab91815260200190565b60408051601f19818403018152908290526102c5916112dc565b602060405180830381855afa1580156102e2573d6000803e3d6000fd5b505060405180516bffffffffffffffffffffffff19606095861b8116602084015293851b84166034830152841b831660488201529287901b909116605c830152506070810187905260900160408051601f1981840301815290829052610347916112dc565b602060405180830381855afa158015610364573d6000803e3d6000fd5b50506040805151600089815260208190529190912054606091821b9350901b6bffffffffffffffffffffffff199081169083161490506103e65760405162461bcd60e51b815260206004820152601360248201527f496e76616c6964207061796d656e7448617368000000000000000000000000006044820152606401610219565b6000868152602081815260409182902080547fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff167c020000000000000000000000000000000000000000000000000000000017905581518881529081018690527f36c177bcb01c6d568244f05261e2946c8c977fa50822f3fa098c470770ee1f3e91015b60405180910390a173ffffffffffffffffffffffffffffffffffffffff83166104c057604051339086156108fc029087906000818181858888f193505050501580156104ba573d6000803e3d6000fd5b506104e1565b6104e173ffffffffffffffffffffffffffffffffffffffff84163387610f15565b505050505050565b73ffffffffffffffffffffffffffffffffffffffff83166105725760405162461bcd60e51b815260206004820152602360248201527f52656365697665722063616e6e6f7420626520746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610219565b600034116105e85760405162461bcd60e51b815260206004820152602560248201527f5061796d656e7420616d6f756e74206d7573742062652067726561746572207460448201527f68616e20300000000000000000000000000000000000000000000000000000006064820152608401610219565b600080858152602081905260409020547c0100000000000000000000000000000000000000000000000000000000900460ff16600381111561062c5761062c61111d565b146106795760405162461bcd60e51b815260206004820152601f60248201527f455448207061796d656e7420616c726561647920696e697469616c697a6564006044820152606401610219565b6040516bffffffffffffffffffffffff19606085811b8216602084015233901b81166034830152831660488201526000605c82018190523460708301529060039060900160408051601f19818403018152908290526106d7916112dc565b602060405180830381855afa1580156106f4573d6000803e3d6000fd5b5050604080518051606080830184521b6bffffffffffffffffffffffff198116825267ffffffffffffffff861660208301529350915081016001905260008681526020818152604091829020835181549285015167ffffffffffffffff1674010000000000000000000000000000000000000000027fffffffff0000000000000000000000000000000000000000000000000000000090931660609190911c179190911780825591830151909182907fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff167c01000000000000000000000000000000000000000000000000000000008360038111156107f5576107f561111d565b0217905550506040518681527fccc9c05183599bd3135da606eaaf535daffe256e9de33c048014cffcccd4ad57915060200160405180910390a15050505050565b60016000868152602081905260409020547c0100000000000000000000000000000000000000000000000000000000900460ff16600381111561087b5761087b61111d565b146108ee5760405162461bcd60e51b815260206004820152602a60248201527f496e76616c6964207061796d656e742073746174652e204d757374206265205060448201527f61796d656e7453656e74000000000000000000000000000000000000000000006064820152608401610219565b6040516bffffffffffffffffffffffff19606083811b8216602084015233811b82166034840152818616604884015284901b16605c8201526070810185905260009060039060900160408051601f1981840301815290829052610950916112dc565b602060405180830381855afa15801561096d573d6000803e3d6000fd5b50506040805151600089815260208190529190912054606091821b9350901b6bffffffffffffffffffffffff199081169083161490506109ef5760405162461bcd60e51b815260206004820152601360248201527f496e76616c6964207061796d656e7448617368000000000000000000000000006044820152606401610219565b60008681526020819052604090205474010000000000000000000000000000000000000000900467ffffffffffffffff16421015610a955760405162461bcd60e51b815260206004820152603160248201527f43757272656e742074696d657374616d70206469646e2774206578636565642060448201527f7061796d656e74206c6f636b2074696d650000000000000000000000000000006064820152608401610219565b6000868152602081815260409182902080547fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff167c030000000000000000000000000000000000000000000000000000000017905590518781527f1797d500133f8e427eb9da9523aa4a25cb40f50ebc7dbda3c7c81778973f35ba910161046a565b73ffffffffffffffffffffffffffffffffffffffff8316610ba05760405162461bcd60e51b815260206004820152602360248201527f52656365697665722063616e6e6f7420626520746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610219565b73ffffffffffffffffffffffffffffffffffffffff8416610c035760405162461bcd60e51b815260206004820152601c60248201527f546f6b656e20616464726573732063616e6e6f74206265207a65726f000000006044820152606401610219565b60008511610c795760405162461bcd60e51b815260206004820152602560248201527f5061796d656e7420616d6f756e74206d7573742062652067726561746572207460448201527f68616e20300000000000000000000000000000000000000000000000000000006064820152608401610219565b600080878152602081905260409020547c0100000000000000000000000000000000000000000000000000000000900460ff166003811115610cbd57610cbd61111d565b14610d305760405162461bcd60e51b815260206004820152602160248201527f4552433230207061796d656e7420616c726561647920696e697469616c697a6560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610219565b6040516bffffffffffffffffffffffff19606085811b8216602084015233811b82166034840152818516604884015286901b16605c8201526070810186905260009060039060900160408051601f1981840301815290829052610d92916112dc565b602060405180830381855afa158015610daf573d6000803e3d6000fd5b5050604080518051606080830184521b6bffffffffffffffffffffffff198116825267ffffffffffffffff861660208301529350915081016001905260008881526020818152604091829020835181549285015167ffffffffffffffff1674010000000000000000000000000000000000000000027fffffffff0000000000000000000000000000000000000000000000000000000090931660609190911c179190911780825591830151909182907fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff167c0100000000000000000000000000000000000000000000000000000000836003811115610eb057610eb061111d565b0217905550506040518881527fccc9c05183599bd3135da606eaaf535daffe256e9de33c048014cffcccd4ad57915060200160405180910390a1610f0c73ffffffffffffffffffffffffffffffffffffffff8616333089610f9b565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff838116602483015260448201839052610f9691859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050610fe7565b505050565b60405173ffffffffffffffffffffffffffffffffffffffff8481166024830152838116604483015260648201839052610fe19186918216906323b872dd90608401610f4f565b50505050565b600080602060008451602086016000885af18061100a576040513d6000823e3d81fd5b50506000513d9150811561102257806001141561103c565b73ffffffffffffffffffffffffffffffffffffffff84163b155b15610fe1576040517f5274afe700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85166004820152602401610219565b803573ffffffffffffffffffffffffffffffffffffffff811681146110af57600080fd5b919050565b600080600080600060a086880312156110cc57600080fd5b8535945060208601359350604086013592506110ea6060870161108b565b91506110f86080870161108b565b90509295509295909350565b60006020828403121561111657600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6bffffffffffffffffffffffff198416815267ffffffffffffffff8316602082015260608101600483106111a9577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b826040830152949350505050565b80356bffffffffffffffffffffffff19811681146110af57600080fd5b803567ffffffffffffffff811681146110af57600080fd5b6000806000806080858703121561120257600080fd5b843593506112126020860161108b565b9250611220604086016111b7565b915061122e606086016111d4565b905092959194509250565b600080600080600060a0868803121561125157600080fd5b8535945060208601359350611268604087016111b7565b92506110ea6060870161108b565b60008060008060008060c0878903121561128f57600080fd5b86359550602087013594506112a66040880161108b565b93506112b46060880161108b565b92506112c2608088016111b7565b91506112d060a088016111d4565b90509295509295509295565b6000825160005b818110156112fd57602081860181015185830152016112e3565b506000920191825250919050565b60006020828403121561131d57600080fd5b505191905056fea264697066735822122038c75c7971f79661b8ba328d5da539577df3351edcffdd121284740a6c16deb664736f6c63430008210033 \ No newline at end of file diff --git a/mm2src/mm2_test_helpers/contract_bytes/usdt_contract_bytes b/mm2src/mm2_test_helpers/contract_bytes/usdt_contract_bytes new file mode 100644 index 0000000000..5b00734326 --- /dev/null +++ b/mm2src/mm2_test_helpers/contract_bytes/usdt_contract_bytes @@ -0,0 +1 @@ +606060405260008060146101000a81548160ff0219169083151502179055506000600355600060045534156200003457600080fd5b60405162002d7c38038062002d7c83398101604052808051906020019091908051820191906020018051820191906020018051906020019091905050336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550836001819055508260079080519060200190620000cf9291906200017a565b508160089080519060200190620000e89291906200017a565b508060098190555083600260008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506000600a60146101000a81548160ff0219169083151502179055505050505062000229565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620001bd57805160ff1916838001178555620001ee565b82800160010185558215620001ee579182015b82811115620001ed578251825591602001919060010190620001d0565b5b509050620001fd919062000201565b5090565b6200022691905b808211156200022257600081600090555060010162000208565b5090565b90565b612b4380620002396000396000f300606060405260043610610196576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde031461019b5780630753c30c14610229578063095ea7b3146102625780630e136b19146102a45780630ecb93c0146102d157806318160ddd1461030a57806323b872dd1461033357806326976e3f1461039457806327e235e3146103e9578063313ce56714610436578063353907141461045f5780633eaaf86b146104885780633f4ba83a146104b157806359bf1abe146104c65780635c658165146105175780635c975abb1461058357806370a08231146105b05780638456cb59146105fd578063893d20e8146106125780638da5cb5b1461066757806395d89b41146106bc578063a9059cbb1461074a578063c0324c771461078c578063cc872b66146107b8578063db006a75146107db578063dd62ed3e146107fe578063dd644f721461086a578063e47d606014610893578063e4997dc5146108e4578063e5b5019a1461091d578063f2fde38b14610946578063f3bdc2281461097f575b600080fd5b34156101a657600080fd5b6101ae6109b8565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101ee5780820151818401526020810190506101d3565b50505050905090810190601f16801561021b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561023457600080fd5b610260600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610a56565b005b341561026d57600080fd5b6102a2600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610b73565b005b34156102af57600080fd5b6102b7610cc1565b604051808215151515815260200191505060405180910390f35b34156102dc57600080fd5b610308600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610cd4565b005b341561031557600080fd5b61031d610ded565b6040518082815260200191505060405180910390f35b341561033e57600080fd5b610392600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610ebd565b005b341561039f57600080fd5b6103a761109d565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156103f457600080fd5b610420600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506110c3565b6040518082815260200191505060405180910390f35b341561044157600080fd5b6104496110db565b6040518082815260200191505060405180910390f35b341561046a57600080fd5b6104726110e1565b6040518082815260200191505060405180910390f35b341561049357600080fd5b61049b6110e7565b6040518082815260200191505060405180910390f35b34156104bc57600080fd5b6104c46110ed565b005b34156104d157600080fd5b6104fd600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506111ab565b604051808215151515815260200191505060405180910390f35b341561052257600080fd5b61056d600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611201565b6040518082815260200191505060405180910390f35b341561058e57600080fd5b610596611226565b604051808215151515815260200191505060405180910390f35b34156105bb57600080fd5b6105e7600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611239565b6040518082815260200191505060405180910390f35b341561060857600080fd5b610610611348565b005b341561061d57600080fd5b610625611408565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561067257600080fd5b61067a611431565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156106c757600080fd5b6106cf611456565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561070f5780820151818401526020810190506106f4565b50505050905090810190601f16801561073c5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561075557600080fd5b61078a600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506114f4565b005b341561079757600080fd5b6107b6600480803590602001909190803590602001909190505061169e565b005b34156107c357600080fd5b6107d96004808035906020019091905050611783565b005b34156107e657600080fd5b6107fc600480803590602001909190505061197a565b005b341561080957600080fd5b610854600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611b0d565b6040518082815260200191505060405180910390f35b341561087557600080fd5b61087d611c52565b6040518082815260200191505060405180910390f35b341561089e57600080fd5b6108ca600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611c58565b604051808215151515815260200191505060405180910390f35b34156108ef57600080fd5b61091b600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611c78565b005b341561092857600080fd5b610930611d91565b6040518082815260200191505060405180910390f35b341561095157600080fd5b61097d600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611db5565b005b341561098a57600080fd5b6109b6600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611e8a565b005b60078054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610a4e5780601f10610a2357610100808354040283529160200191610a4e565b820191906000526020600020905b815481529060010190602001808311610a3157829003601f168201915b505050505081565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610ab157600080fd5b6001600a60146101000a81548160ff02191690831515021790555080600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507fcc358699805e9a8b7f77b522628c7cb9abd07d9efb86b6fb616af1609036a99e81604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b604060048101600036905010151515610b8b57600080fd5b600a60149054906101000a900460ff1615610cb157600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663aee92d333385856040518463ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050600060405180830381600087803b1515610c9857600080fd5b6102c65a03f11515610ca957600080fd5b505050610cbc565b610cbb838361200e565b5b505050565b600a60149054906101000a900460ff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610d2f57600080fd5b6001600660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507f42e160154868087d6bfdc0ca23d96a1c1cfa32f1b72ba9ba27b69b98a0d819dc81604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b6000600a60149054906101000a900460ff1615610eb457600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166318160ddd6000604051602001526040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b1515610e9257600080fd5b6102c65a03f11515610ea357600080fd5b505050604051805190509050610eba565b60015490505b90565b600060149054906101000a900460ff16151515610ed957600080fd5b600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151515610f3257600080fd5b600a60149054906101000a900460ff161561108c57600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638b477adb338585856040518563ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001945050505050600060405180830381600087803b151561107357600080fd5b6102c65a03f1151561108457600080fd5b505050611098565b6110978383836121ab565b5b505050565b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60026020528060005260406000206000915090505481565b60095481565b60045481565b60015481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561114857600080fd5b600060149054906101000a900460ff16151561116357600080fd5b60008060146101000a81548160ff0219169083151502179055507f7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b3360405160405180910390a1565b6000600660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b6005602052816000526040600020602052806000526040600020600091509150505481565b600060149054906101000a900460ff1681565b6000600a60149054906101000a900460ff161561133757600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231836000604051602001526040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600087803b151561131557600080fd5b6102c65a03f1151561132657600080fd5b505050604051805190509050611343565b61134082612652565b90505b919050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156113a357600080fd5b600060149054906101000a900460ff161515156113bf57600080fd5b6001600060146101000a81548160ff0219169083151502179055507f6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff62560405160405180910390a1565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60088054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156114ec5780601f106114c1576101008083540402835291602001916114ec565b820191906000526020600020905b8154815290600101906020018083116114cf57829003601f168201915b505050505081565b600060149054906101000a900460ff1615151561151057600080fd5b600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615151561156957600080fd5b600a60149054906101000a900460ff161561168f57600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636e18980a3384846040518463ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050600060405180830381600087803b151561167657600080fd5b6102c65a03f1151561168757600080fd5b50505061169a565b611699828261269b565b5b5050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156116f957600080fd5b60148210151561170857600080fd5b60328110151561171757600080fd5b81600381905550611736600954600a0a82612a0390919063ffffffff16565b6004819055507fb044a1e409eac5c48e5af22d4af52670dd1a99059537a78b31b48c6500a6354e600354600454604051808381526020018281526020019250505060405180910390a15050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156117de57600080fd5b60015481600154011115156117f257600080fd5b600260008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205481600260008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054011115156118c257600080fd5b80600260008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550806001600082825401925050819055507fcb8241adb0c3fdb35b70c24ce35c5eb0c17af7431c99f827d44a445ca624176a816040518082815260200191505060405180910390a150565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156119d557600080fd5b80600154101515156119e657600080fd5b80600260008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515611a5557600080fd5b8060016000828254039250508190555080600260008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055507f702d5967f45f6513a38ffc42d6ba9bf230bd40e8f53b16363c7eb4fd2deb9a44816040518082815260200191505060405180910390a150565b6000600a60149054906101000a900460ff1615611c3f57600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e84846000604051602001526040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200192505050602060405180830381600087803b1515611c1d57600080fd5b6102c65a03f11515611c2e57600080fd5b505050604051805190509050611c4c565b611c498383612a3e565b90505b92915050565b60035481565b60066020528060005260406000206000915054906101000a900460ff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515611cd357600080fd5b6000600660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fd7e9ec6e6ecd65492dce6bf513cd6867560d49544421d0783ddf06e76c24470c81604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515611e1057600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141515611e8757806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b50565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515611ee757600080fd5b600660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515611f3f57600080fd5b611f4882611239565b90506000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550806001600082825403925050819055507f61e6e66b0d6339b2980aecc6ccc0039736791f0ccde9ed512e789a7fbdd698c68282604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a15050565b60406004810160003690501015151561202657600080fd5b600082141580156120b457506000600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205414155b1515156120c057600080fd5b81600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a3505050565b60008060006060600481016000369050101515156121c857600080fd5b600560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054935061227061271061226260035488612a0390919063ffffffff16565b612ac590919063ffffffff16565b92506004548311156122825760045492505b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84101561233e576122bd8585612ae090919063ffffffff16565b600560008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b6123518386612ae090919063ffffffff16565b91506123a585600260008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054612ae090919063ffffffff16565b600260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061243a82600260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054612af990919063ffffffff16565b600260008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555060008311156125e4576124f983600260008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054612af990919063ffffffff16565b600260008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040518082815260200191505060405180910390a35b8573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a350505050505050565b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6000806040600481016000369050101515156126b657600080fd5b6126df6127106126d160035487612a0390919063ffffffff16565b612ac590919063ffffffff16565b92506004548311156126f15760045492505b6127048385612ae090919063ffffffff16565b915061275884600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054612ae090919063ffffffff16565b600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506127ed82600260008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054612af990919063ffffffff16565b600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506000831115612997576128ac83600260008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054612af990919063ffffffff16565b600260008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040518082815260200191505060405180910390a35b8473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a35050505050565b6000806000841415612a185760009150612a37565b8284029050828482811515612a2957fe5b04141515612a3357fe5b8091505b5092915050565b6000600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b6000808284811515612ad357fe5b0490508091505092915050565b6000828211151515612aee57fe5b818303905092915050565b6000808284019050838110151515612b0d57fe5b80915050929150505600a165627a7a72305820645ee12d73db47fd78ba77fa1f824c3c8f9184061b3b10386beb4dc9236abb280029000000000000000000000000000000000000000000000000000000174876e800000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a546574686572205553440000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045553445400000000000000000000000000000000000000000000000000000000 \ No newline at end of file diff --git a/mm2src/mm2_test_helpers/dummy_files/usdt_abi.json b/mm2src/mm2_test_helpers/dummy_files/usdt_abi.json new file mode 100644 index 0000000000..b59b944a26 --- /dev/null +++ b/mm2src/mm2_test_helpers/dummy_files/usdt_abi.json @@ -0,0 +1,671 @@ +[ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_upgradedAddress", + "type": "address" + } + ], + "name": "deprecate", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "deprecated", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_evilUser", + "type": "address" + } + ], + "name": "addBlackList", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "upgradedAddress", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + } + ], + "name": "balances", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "maximumFee", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "_totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "unpause", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_maker", + "type": "address" + } + ], + "name": "getBlackListStatus", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + }, + { + "name": "", + "type": "address" + } + ], + "name": "allowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "paused", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "who", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "pause", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getOwner", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "owner", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "newBasisPoints", + "type": "uint256" + }, + { + "name": "newMaxFee", + "type": "uint256" + } + ], + "name": "setParams", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "amount", + "type": "uint256" + } + ], + "name": "issue", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "amount", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "remaining", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "basisPointsRate", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + } + ], + "name": "isBlackListed", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_clearedUser", + "type": "address" + } + ], + "name": "removeBlackList", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "MAX_UINT", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_blackListedUser", + "type": "address" + } + ], + "name": "destroyBlackFunds", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "name": "_initialSupply", + "type": "uint256" + }, + { + "name": "_name", + "type": "string" + }, + { + "name": "_symbol", + "type": "string" + }, + { + "name": "_decimals", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Issue", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "newAddress", + "type": "address" + } + ], + "name": "Deprecate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "feeBasisPoints", + "type": "uint256" + }, + { + "indexed": false, + "name": "maxFee", + "type": "uint256" + } + ], + "name": "Params", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "_blackListedUser", + "type": "address" + }, + { + "indexed": false, + "name": "_balance", + "type": "uint256" + } + ], + "name": "DestroyedBlackFunds", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "_user", + "type": "address" + } + ], + "name": "AddedBlackList", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "_user", + "type": "address" + } + ], + "name": "RemovedBlackList", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "Pause", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "Unpause", + "type": "event" + } +] diff --git a/mm2src/mm2_test_helpers/src/for_tests.rs b/mm2src/mm2_test_helpers/src/for_tests.rs index 4e6d733ac5..207f028dc8 100644 --- a/mm2src/mm2_test_helpers/src/for_tests.rs +++ b/mm2src/mm2_test_helpers/src/for_tests.rs @@ -954,6 +954,26 @@ pub fn erc20_dev_conf(contract_address: &str) -> Json { }) } +/// USDT token configuration used for dockerized Geth dev node. +/// Uses 6 decimals like real mainnet USDT. +pub fn usdt_dev_conf(contract_address: &str) -> Json { + json!({ + "coin": "USDT", + "name": "usdt", + "mm2": 1, + "decimals": 6, + "derivation_path": "m/44'/60'", + "protocol": { + "type": "ERC20", + "protocol_data": { + "platform": "ETH", + "contract_address": contract_address, + } + }, + "max_eth_tx_type": 2 + }) +} + /// ERC20 token configuration used for dockerized tests on Sepolia pub fn sepolia_erc20_dev_conf(contract_address: &str) -> Json { let mut conf = erc20_dev_conf(contract_address);