-
Notifications
You must be signed in to change notification settings - Fork 94
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
[r2r] wait for EVM approval transaction confirmation #1706
Changes from 2 commits
6671a23
be6edaf
04fcbdc
b56f307
c28474b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2823,10 +2823,16 @@ impl EthCoin { | |
} | ||
|
||
fn send_hash_time_locked_payment(&self, args: SendPaymentArgs<'_>) -> EthTxFut { | ||
const APPROVE_TX_CONFIRMATIONS: u64 = 1; | ||
const APPROVE_TX_CHECK_EVERY: u64 = 5; | ||
|
||
let receiver_addr = try_tx_fus!(addr_from_raw_pubkey(args.other_pubkey)); | ||
let swap_contract_address = try_tx_fus!(args.swap_contract_address.try_to_address()); | ||
let id = self.etomic_swap_id(args.time_lock, args.secret_hash); | ||
let trade_amount = try_tx_fus!(wei_from_big_decimal(&args.amount, self.decimals)); | ||
let watcher_reward = args.watcher_reward.map(U256::from); | ||
let time_lock = U256::from(args.time_lock); | ||
let gas = U256::from(ETH_GAS); | ||
|
||
let secret_hash = if args.secret_hash.len() == 32 { | ||
ripemd160(args.secret_hash).to_vec() | ||
|
@@ -2836,31 +2842,32 @@ impl EthCoin { | |
|
||
match &self.coin_type { | ||
EthCoinType::Eth => { | ||
let function_name = get_function_name("ethPayment", args.watcher_reward.is_some()); | ||
let function_name = get_function_name("ethPayment", watcher_reward.is_some()); | ||
let function = try_tx_fus!(SWAP_CONTRACT.function(&function_name)); | ||
let mut value = trade_amount; | ||
|
||
let data = match args.watcher_reward { | ||
let mut value = trade_amount; | ||
let data = match watcher_reward { | ||
Some(reward) => { | ||
value += U256::from(reward); | ||
value += reward; | ||
|
||
try_tx_fus!(function.encode_input(&[ | ||
Token::FixedBytes(id), | ||
Token::Address(receiver_addr), | ||
Token::FixedBytes(secret_hash), | ||
Token::Uint(U256::from(args.time_lock)), | ||
Token::Uint(U256::from(reward)), | ||
Token::Uint(time_lock), | ||
Token::Uint(reward), | ||
])) | ||
}, | ||
None => try_tx_fus!(function.encode_input(&[ | ||
Token::FixedBytes(id), | ||
Token::Address(receiver_addr), | ||
Token::FixedBytes(secret_hash), | ||
Token::Uint(U256::from(args.time_lock)), | ||
Token::Uint(time_lock), | ||
])), | ||
}; | ||
drop_mutability!(value); | ||
|
||
self.sign_and_send_transaction(value, Action::Call(swap_contract_address), data, U256::from(ETH_GAS)) | ||
self.sign_and_send_transaction(value, Action::Call(swap_contract_address), data, gas) | ||
}, | ||
EthCoinType::Erc20 { | ||
platform: _, | ||
|
@@ -2870,7 +2877,7 @@ impl EthCoin { | |
.allowance(swap_contract_address) | ||
.map_err(|e| TransactionErr::Plain(ERRL!("{}", e))); | ||
|
||
let function_name = get_function_name("erc20Payment", args.watcher_reward.is_some()); | ||
let function_name = get_function_name("erc20Payment", watcher_reward.is_some()); | ||
let function = try_tx_fus!(SWAP_CONTRACT.function(&function_name)); | ||
|
||
let data = try_tx_fus!(function.encode_input(&[ | ||
|
@@ -2879,30 +2886,42 @@ impl EthCoin { | |
Token::Address(*token_addr), | ||
Token::Address(receiver_addr), | ||
Token::FixedBytes(secret_hash), | ||
Token::Uint(U256::from(args.time_lock)) | ||
Token::Uint(time_lock) | ||
])); | ||
let value = U256::from(args.watcher_reward.unwrap_or(0)); | ||
// wait for the approval tx confirmation only half the time required for the actual htlc tx confirmation | ||
let wait_for_approval_confirmation_until = args.wait_for_confirmation_until / 2; | ||
|
||
let arc = self.clone(); | ||
Box::new(allowance_fut.and_then(move |allowed| -> EthTxFut { | ||
if allowed < value { | ||
if allowed < trade_amount { | ||
Box::new( | ||
arc.approve(swap_contract_address, U256::max_value()) | ||
.and_then(move |_approved| { | ||
arc.sign_and_send_transaction( | ||
value, | ||
Action::Call(swap_contract_address), | ||
data, | ||
U256::from(ETH_GAS), | ||
.and_then(move |approved| { | ||
// make sure the approve tx is confirmed before sending the htlc tx | ||
arc.wait_for_confirmations( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I decided to wait for confirmation of the approve transaction, alternatively, we can loop over the allowance fn and check until the amount is allowed. What do you think is the better solution @caglaryucekaya? checking allowance fn might be a cheaper call but I am not sure. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. https://www.quicknode.com/docs/ethereum/api_credits Quicknode has an API credit measure here for each method based on its complexity. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the detailed research/explanation for this. Will fix it :) |
||
&BytesJson::from(approved.tx_hex()), | ||
APPROVE_TX_CONFIRMATIONS, | ||
false, | ||
wait_for_approval_confirmation_until, | ||
APPROVE_TX_CHECK_EVERY, | ||
) | ||
.map_err(TransactionErr::Plain) | ||
.and_then(move |_confirmed| { | ||
arc.sign_and_send_transaction( | ||
watcher_reward.unwrap_or_else(|| 0.into()), | ||
Action::Call(swap_contract_address), | ||
data, | ||
gas, | ||
) | ||
}) | ||
}), | ||
) | ||
} else { | ||
Box::new(arc.sign_and_send_transaction( | ||
value, | ||
watcher_reward.unwrap_or_else(|| 0.into()), | ||
Action::Call(swap_contract_address), | ||
data, | ||
U256::from(ETH_GAS), | ||
gas, | ||
)) | ||
} | ||
})) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@caglaryucekaya Do you think the wait period should be reduced for the approval confirmation? I don't want the check for confirmation to fail quickly if there is no new blocks for some time but if there is a problem with the approval transaction we want it to fail quickly, so that is the trade off between longer vs shorter wait time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could put some random limit on it, but I think we can leave it this way. If the transaction is sent successfully with enough gas and correct addresses it shouldn't fail. Are there any other reasons why it can fail?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I think so too.
There is a more general problem with block reorganization specially with polygon, but this should be solved using a higher value for required confs for both taker and maker and if the approve transaction disappears, dependant transactions will fail too, so I see no problem with the current approach.