diff --git a/contract/Cargo.lock b/contract/Cargo.lock index 68e4a5f6..3e0c418e 100644 --- a/contract/Cargo.lock +++ b/contract/Cargo.lock @@ -304,9 +304,9 @@ dependencies = [ [[package]] name = "coreum-wasm-sdk" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de2207655b1d9ddbb228d96b9900d8726ebead2d382a893492806230ead2daa0" +checksum = "a465bdcbfa6b84b7c9981e2797f1a134c0663f3f6e39abb22abc2255884dcc85" dependencies = [ "chrono", "cosmwasm-schema", @@ -1784,9 +1784,9 @@ checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" [[package]] name = "serde" -version = "1.0.192" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" dependencies = [ "serde_derive", ] @@ -1820,9 +1820,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.192" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", diff --git a/contract/Cargo.toml b/contract/Cargo.toml index 4f4eb459..3a5211b4 100644 --- a/contract/Cargo.toml +++ b/contract/Cargo.toml @@ -24,7 +24,7 @@ incremental = false overflow-checks = true [dependencies] -coreum-wasm-sdk = "0.2.3" +coreum-wasm-sdk = "0.2.4" cosmwasm-schema = "1.5.0" cosmwasm-std = { version = "1.5.0", features = ["cosmwasm_1_1"] } cw-ownable = "0.5.1" diff --git a/contract/src/contract.rs b/contract/src/contract.rs index bb000d9a..f6bf7c66 100644 --- a/contract/src/contract.rs +++ b/contract/src/contract.rs @@ -4,7 +4,7 @@ use crate::{ error::ContractError, evidence::{handle_evidence, hash_bytes, Evidence, OperationResult, TransactionResult}, msg::{ - AvailableTicketsResponse, CoreumTokenResponse, CoreumTokensResponse, ExecuteMsg, + AvailableTicketsResponse, CoreumTokensResponse, ExecuteMsg, InstantiateMsg, PendingOperationsResponse, QueryMsg, XRPLTokensResponse, }, operation::{ @@ -228,6 +228,8 @@ fn register_coreum_token( ) -> CoreumResult { assert_owner(deps.storage, &sender)?; + validate_sending_precision(sending_precision, decimals)?; + if COREUM_TOKENS.has(deps.storage, denom.clone()) { return Err(ContractError::CoreumTokenAlreadyRegistered { denom }); } @@ -285,10 +287,7 @@ fn register_xrpl_token( validate_xrpl_issuer_and_currency(issuer.clone(), currency.clone())?; - // Minimum and maximum sending precisions we allow - if !(MIN_SENDING_PRECISION..=MAX_SENDING_PRECISION).contains(&sending_precision) { - return Err(ContractError::InvalidSendingPrecision {}); - } + validate_sending_precision(sending_precision, XRPL_TOKENS_DECIMALS)?; // We want to check that exactly the issue fee was sent, not more. check_issue_fee(&deps, &info)?; @@ -405,6 +404,7 @@ fn save_evidence(deps: DepsMut, sender: Addr, evidence: Evidence) -> CoreumResul false => XRPL_TOKENS_DECIMALS, }; + // Here we simply truncate because the Coreum tokens corresponding to XRPL originated tokens have the same decimals as their corresponding Coreum tokens let amount_to_send = truncate_amount(token.sending_precision, decimals, amount)?; if amount_to_send @@ -440,14 +440,18 @@ fn save_evidence(deps: DepsMut, sender: Addr, evidence: Evidence) -> CoreumResul } token } - // In theory this will never happen because any token issued from the multisig address is a token that was bridged from Coreum so it will be registered. + // In practice this will never happen because any token issued from the multisig address is a token that was bridged from Coreum so it will be registered. // This could theoretically happen if the multisig address on XRPL issued a token on its own and then tried to bridge it None => return Err(ContractError::TokenNotRegistered {}), }; - // TODO(keyleu): add/update tests for it - // We build the amount_to_send here since it includes validation against zero amount after the truncation - let amount_to_send = truncate_amount(token.sending_precision, token.decimals, amount)?; + // We first convert the amount we receive with XRPL decimals to the corresponding decimals in Coreum and then we apply the truncation according to sending precision. + let amount_to_send = convert_and_truncate_amount( + token.sending_precision, + XRPL_TOKENS_DECIMALS, + token.decimals, + amount, + )?; if threshold_reached { // TODO(keyleu): for now we are SENDING back the entire amount but when fees are implemented this will not happen and part of the amount will be sent and funds will be collected @@ -700,7 +704,9 @@ fn send_to_xrpl( false => XRPL_TOKENS_DECIMALS, }; + // We don't need any decimal conversion because the token is an XRPL originated token and they are issued with same decimals amount_to_send = truncate_amount(xrpl_token.sending_precision, decimals, funds.amount)?; + // Since tokens are being sent back we need to burn them in the contract // TODO(keyleu): for now we are BURNING the entire amount but when fees are implemented this will not happen and part of the amount will be burned and fees will be collected let burn_msg = CosmosMsg::from(CoreumMsg::AssetFT(assetft::Msg::Burn { @@ -724,8 +730,15 @@ fn send_to_xrpl( decimals = coreum_token.decimals; issuer = config.bridge_xrpl_address; currency = coreum_token.xrpl_currency; - amount_to_send = - truncate_amount(coreum_token.sending_precision, decimals, funds.amount)?; + + // Since this is a Coreum originated token with different decimals, we are first going to truncate according to sending precision and then we will convert + // to corresponding XRPL decimals. + amount_to_send = truncate_and_convert_amount( + coreum_token.sending_precision, + decimals, + XRPL_TOKENS_DECIMALS, + funds.amount, + )?; // For Coreum originated tokens we need to check that we are not going over max bridge amount. if deps @@ -770,10 +783,7 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { } QueryMsg::CoreumTokens { offset, limit } => { to_json_binary(&query_coreum_tokens(deps, offset, limit)?) - } - QueryMsg::CoreumTokenByXRPLCurrency { xrpl_currency } => { - to_json_binary(&query_coreum_token_by_xrpl_currency(deps, xrpl_currency)?) - } + }, QueryMsg::Ownership {} => to_json_binary(&get_ownership(deps.storage)?), QueryMsg::PendingOperations {} => to_json_binary(&query_pending_operations(deps)?), QueryMsg::AvailableTickets {} => to_json_binary(&query_available_tickets(deps)?), @@ -821,19 +831,6 @@ fn query_coreum_tokens( Ok(CoreumTokensResponse { tokens }) } -fn query_coreum_token_by_xrpl_currency( - deps: Deps, - xrpl_currency: String, -) -> StdResult { - let token = COREUM_TOKENS - .idx - .xrpl_currency - .item(deps.storage, xrpl_currency)? - .map(|(_, ct)| ct); - - Ok(CoreumTokenResponse { token }) -} - fn query_pending_operations(deps: Deps) -> StdResult { let operations: Vec = PENDING_OPERATIONS .range(deps.storage, None, None, Order::Ascending) @@ -889,13 +886,29 @@ pub fn validate_xrpl_issuer_and_currency( Ok(()) } +pub fn validate_sending_precision( + sending_precision: i32, + decimals: u32, +) -> Result<(), ContractError> { + // Minimum and maximum sending precisions we allow + if !(MIN_SENDING_PRECISION..=MAX_SENDING_PRECISION).contains(&sending_precision) { + return Err(ContractError::InvalidSendingPrecision {}); + } + + if sending_precision > decimals.try_into().unwrap() { + return Err(ContractError::TokenSendingPrecisionTooHigh {}); + } + Ok(()) +} + +// Function used to truncate the amount to not send tokens over the sending precision. fn truncate_amount( sending_precision: i32, decimals: u32, amount: Uint128, ) -> Result { // To get exactly by how much we need to divide the original amount - // Example: if sending precision = -1. Exponent will be 15 - ( - 1) = 16 for XRPL tokens so we will divide the original amount by 1e16 + // Example: if sending precision = -1. Exponent will be 15 - (-1) = 16 for XRPL tokens so we will divide the original amount by 1e16 // Example: if sending precision = 14. Exponent will be 15 - 14 = 1 for XRPL tokens so we will divide the original amount by 10 let exponent = decimals as i32 - sending_precision; @@ -908,6 +921,49 @@ fn truncate_amount( Ok(amount_to_send.checked_mul(Uint128::new(10u128.pow(exponent.unsigned_abs())))?) } +// Function used to convert the amount received from XRPL with XRPL decimals to the Coreum amount with Coreum decimals +fn convert_amount_decimals( + from_decimals: u32, + to_decimals: u32, + amount: Uint128, +) -> Result { + let converted_amount = match from_decimals.cmp(&to_decimals) { + std::cmp::Ordering::Less => amount.checked_mul(Uint128::new( + 10u128.pow(to_decimals.saturating_sub(from_decimals)), + ))?, + std::cmp::Ordering::Greater => amount.checked_div(Uint128::new( + 10u128.pow(from_decimals.saturating_sub(to_decimals)), + ))?, + std::cmp::Ordering::Equal => amount, + }; + + Ok(converted_amount) +} + +// Helper function to combine the conversion and truncation of amounts. +fn convert_and_truncate_amount( + sending_precision: i32, + from_decimals: u32, + to_decimals: u32, + amount: Uint128, +) -> Result { + let converted_amount = convert_amount_decimals(from_decimals, to_decimals, amount)?; + let truncated_amount = truncate_amount(sending_precision, to_decimals, converted_amount)?; + Ok(truncated_amount) +} + +// Helper function to combine the truncation and conversion of amounts +fn truncate_and_convert_amount( + sending_precision: i32, + from_decimals: u32, + to_decimals: u32, + amount: Uint128, +) -> Result { + let truncated_amount = truncate_amount(sending_precision, from_decimals, amount)?; + let converted_amount = convert_amount_decimals(from_decimals, to_decimals, truncated_amount)?; + Ok(converted_amount) +} + fn is_token_xrp(issuer: String, currency: String) -> bool { issuer == XRP_ISSUER && currency == XRP_CURRENCY } diff --git a/contract/src/error.rs b/contract/src/error.rs index 3d2c6464..589d8cd1 100644 --- a/contract/src/error.rs +++ b/contract/src/error.rs @@ -145,4 +145,9 @@ pub enum ContractError { "InvalidSendingPrecision: The sending precision can't be more than the token decimals or less than the negative token decimals" )] InvalidSendingPrecision {}, + + #[error( + "TokenSendingPrecisionTooHigh: The sending precision can't be more than the token decimals" + )] + TokenSendingPrecisionTooHigh {}, } diff --git a/contract/src/msg.rs b/contract/src/msg.rs index aea00610..07495b8c 100644 --- a/contract/src/msg.rs +++ b/contract/src/msg.rs @@ -76,9 +76,6 @@ pub enum QueryMsg { offset: Option, limit: Option, }, - #[returns(CoreumTokenResponse)] - #[serde(rename = "coreum_token_by_xrpl_currency")] - CoreumTokenByXRPLCurrency { xrpl_currency: String }, #[returns(PendingOperationsResponse)] PendingOperations {}, #[returns(AvailableTicketsResponse)] @@ -95,11 +92,6 @@ pub struct CoreumTokensResponse { pub tokens: Vec, } -#[cw_serde] -pub struct CoreumTokenResponse { - pub token: Option, -} - #[cw_serde] pub struct PendingOperationsResponse { pub operations: Vec, diff --git a/contract/src/tests.rs b/contract/src/tests.rs index 915c4b10..3a4a41be 100644 --- a/contract/src/tests.rs +++ b/contract/src/tests.rs @@ -15,7 +15,7 @@ mod tests { error::ContractError, evidence::{Evidence, OperationResult, TransactionResult}, msg::{ - AvailableTicketsResponse, CoreumTokenResponse, CoreumTokensResponse, ExecuteMsg, + AvailableTicketsResponse, CoreumTokensResponse, ExecuteMsg, InstantiateMsg, PendingOperationsResponse, QueryMsg, XRPLTokensResponse, }, operation::{Operation, OperationType}, @@ -630,7 +630,7 @@ mod tests { .unwrap(); } - // Register 1 token with same denom, should fail + // Registering a token with same denom, should fail let register_error = wasm .execute::( &contract_addr, @@ -653,6 +653,27 @@ mod tests { .as_str() )); + // Registering a token with invalid sending precision should fail + let register_error = wasm + .execute::( + &contract_addr, + &ExecuteMsg::RegisterCoreumToken { + denom: test_tokens[0].denom.clone(), + decimals: 6, + sending_precision: -17, + max_holding_amount: Uint128::new(1), + }, + &vec![], + &signer, + ) + .unwrap_err(); + + assert!(register_error.to_string().contains( + ContractError::InvalidSendingPrecision {} + .to_string() + .as_str() + )); + // Query all tokens let query_coreum_tokens = wasm .query::( @@ -692,21 +713,6 @@ mod tests { .unwrap(); assert_eq!(query_coreum_tokens.tokens.len(), 1); assert_eq!(query_coreum_tokens.tokens[0].denom, test_tokens[1].denom); - - // Query a token using the xrpl currency - let query_coreum_token_by_xrpl_currency = wasm - .query::( - &contract_addr, - &QueryMsg::CoreumTokenByXRPLCurrency { - xrpl_currency: query_coreum_tokens.tokens[0].xrpl_currency.to_owned(), - }, - ) - .unwrap(); - - assert_eq!( - query_coreum_token_by_xrpl_currency.token.unwrap(), - query_coreum_tokens.tokens[0] - ); } #[test] @@ -1611,7 +1617,7 @@ mod tests { ) .unwrap(); - // Let's issue a token to the sender and register it. + // Let's issue a token where decimals are less than an XRPL token decimals to the sender and register it. let asset_ft = AssetFT::new(&app); let symbol = "TEST".to_string(); let subunit = "utest".to_string(); @@ -1643,7 +1649,7 @@ mod tests { &ExecuteMsg::RegisterCoreumToken { denom: denom.to_owned(), decimals, - sending_precision: 6, + sending_precision: 5, max_holding_amount: Uint128::new(10000000), }, &vec![], @@ -1651,7 +1657,9 @@ mod tests { ) .unwrap(); - let amount_to_send = Uint128::new(1000000); + // It should truncate 1 because sending precision is 5 + let amount_to_send = Uint128::new(1000001); + // Bridge the token to the xrpl receiver address so that we can send it back. wasm.execute::( &contract_addr, @@ -1688,6 +1696,23 @@ mod tests { assert_eq!(request_balance.balance, amount_to_send.to_string()); + // Get the token information + let query_coreum_tokens = wasm + .query::( + &contract_addr, + &QueryMsg::CoreumTokens { + offset: None, + limit: None, + }, + ) + .unwrap(); + + let coreum_originated_token = query_coreum_tokens + .tokens + .iter() + .find(|t| t.denom == denom) + .unwrap(); + // Confirm the operation to remove it from pending operations. let query_pending_operations = wasm .query::( @@ -1696,7 +1721,17 @@ mod tests { ) .unwrap(); + let amount_truncated_and_converted = Uint128::new(1000000000000000); // 100001 -> truncate -> 100000 -> convert -> 1e15 assert_eq!(query_pending_operations.operations.len(), 1); + assert_eq!( + query_pending_operations.operations[0].operation_type, + OperationType::CoreumToXRPLTransfer { + issuer: bridge_xrpl_address.to_owned(), + currency: coreum_originated_token.xrpl_currency.to_owned(), + amount: amount_truncated_and_converted, + recipient: xrpl_receiver_address.to_owned(), + } + ); // Send successfull evidence to remove from queue (tokens should be released on XRPL to the receiver) wasm.execute::( @@ -1724,7 +1759,207 @@ mod tests { assert_eq!(query_pending_operations.operations.len(), 0); - // Get the xrpl bridge address and xrpl currency of the token so that we can send it back. + // Test sending the amount back from XRPL to Coreum + // 10000000000 (1e10) is the minimum we can send back (15 - 5 (sending precision)) + let amount_to_send_back = Uint128::new(10000000000); + + // If we send the token with a different issuer (not multisig address) it should fail + let transfer_error = wasm + .execute::( + &contract_addr, + &ExecuteMsg::SaveEvidence { + evidence: Evidence::XRPLToCoreumTransfer { + tx_hash: generate_hash(), + issuer: generate_xrpl_address(), + currency: coreum_originated_token.xrpl_currency.to_owned(), + amount: amount_to_send_back.clone(), + recipient: Addr::unchecked(sender.address()), + }, + }, + &[], + relayer_account, + ) + .unwrap_err(); + + assert!(transfer_error + .to_string() + .contains(ContractError::TokenNotRegistered {}.to_string().as_str())); + + // If we send the token with a different currency (one that is not the one in the registered token list) it should fail + let transfer_error = wasm + .execute::( + &contract_addr, + &ExecuteMsg::SaveEvidence { + evidence: Evidence::XRPLToCoreumTransfer { + tx_hash: generate_hash(), + issuer: bridge_xrpl_address.to_owned(), + currency: "invalid_currency".to_string(), + amount: amount_to_send_back.clone(), + recipient: Addr::unchecked(sender.address()), + }, + }, + &[], + relayer_account, + ) + .unwrap_err(); + + assert!(transfer_error + .to_string() + .contains(ContractError::TokenNotRegistered {}.to_string().as_str())); + + // Sending under the minimum should fail (minimum - 1) + let transfer_error = wasm + .execute::( + &contract_addr, + &ExecuteMsg::SaveEvidence { + evidence: Evidence::XRPLToCoreumTransfer { + tx_hash: generate_hash(), + issuer: bridge_xrpl_address.to_owned(), + currency: coreum_originated_token.xrpl_currency.to_owned(), + amount: amount_to_send_back.checked_sub(Uint128::one()).unwrap(), + recipient: Addr::unchecked(sender.address()), + }, + }, + &[], + relayer_account, + ) + .unwrap_err(); + + assert!(transfer_error.to_string().contains( + ContractError::AmountSentIsZeroAfterTruncation {} + .to_string() + .as_str() + )); + + // Sending the right evidence should move tokens from the contract to the sender's account + wasm.execute::( + &contract_addr, + &ExecuteMsg::SaveEvidence { + evidence: Evidence::XRPLToCoreumTransfer { + tx_hash: generate_hash(), + issuer: bridge_xrpl_address.to_owned(), + currency: coreum_originated_token.xrpl_currency.to_owned(), + amount: amount_to_send_back.clone(), + recipient: Addr::unchecked(sender.address()), + }, + }, + &[], + relayer_account, + ) + .unwrap(); + + // Check balance of sender and contract + let request_balance = asset_ft + .query_balance(&QueryBalanceRequest { + account: sender.address(), + denom: denom.clone(), + }) + .unwrap(); + + assert_eq!( + request_balance.balance, + initial_amount + .checked_sub(amount_to_send) // initial amount + .unwrap() + .checked_add(Uint128::new(10)) // Amount that we sent back (10) after conversion, the minimum + .unwrap() + .to_string() + ); + + let request_balance = asset_ft + .query_balance(&QueryBalanceRequest { + account: contract_addr.to_owned(), + denom: denom.clone(), + }) + .unwrap(); + + assert_eq!( + request_balance.balance, + amount_to_send + .checked_sub(Uint128::new(10)) + .unwrap() + .to_string() + ); + + // Now let's issue a token where decimals are more than an XRPL token decimals to the sender and register it. + let symbol = "TEST2".to_string(); + let subunit = "utest2".to_string(); + let decimals = 20; + let initial_amount = Uint128::new(200000000000000000000); // 2e20 + asset_ft + .issue( + MsgIssue { + issuer: sender.address(), + symbol, + subunit: subunit.to_owned(), + precision: decimals, + initial_amount: initial_amount.to_string(), + description: "description".to_string(), + features: vec![MINTING as i32], + burn_rate: "0".to_string(), + send_commission_rate: "0".to_string(), + uri: "uri".to_string(), + uri_hash: "uri_hash".to_string(), + }, + &sender, + ) + .unwrap(); + + let denom = format!("{}-{}", subunit, sender.address()).to_lowercase(); + + wasm.execute::( + &contract_addr, + &ExecuteMsg::RegisterCoreumToken { + denom: denom.to_owned(), + decimals, + sending_precision: 10, + max_holding_amount: Uint128::new(200000000000000000000), //2e20 + }, + &vec![], + &signer, + ) + .unwrap(); + + // It should truncate and remove all 9s because they are under precision + let amount_to_send = Uint128::new(100000000019999999999); + + // Bridge the token to the xrpl receiver address so that we can send it back. + wasm.execute::( + &contract_addr, + &ExecuteMsg::SendToXRPL { + recipient: xrpl_receiver_address.to_owned(), + }, + &coins(amount_to_send.u128(), denom.to_owned()), + &sender, + ) + .unwrap(); + + // Check balance of sender and contract + let request_balance = asset_ft + .query_balance(&QueryBalanceRequest { + account: sender.address(), + denom: denom.clone(), + }) + .unwrap(); + + assert_eq!( + request_balance.balance, + initial_amount + .checked_sub(amount_to_send) + .unwrap() + .to_string() + ); + + let request_balance = asset_ft + .query_balance(&QueryBalanceRequest { + account: contract_addr.to_owned(), + denom: denom.clone(), + }) + .unwrap(); + + assert_eq!(request_balance.balance, amount_to_send.to_string()); + + // Get the token information let query_coreum_tokens = wasm .query::( &contract_addr, @@ -1741,8 +1976,55 @@ mod tests { .find(|t| t.denom == denom) .unwrap(); + // Confirm the operation to remove it from pending operations. + let query_pending_operations = wasm + .query::( + &contract_addr, + &QueryMsg::PendingOperations {}, + ) + .unwrap(); + + let amount_truncated_and_converted = Uint128::new(1000000000100000); // 100000000019999999999 -> truncate -> 100000000010000000000 -> convert -> 1000000000100000 + assert_eq!(query_pending_operations.operations.len(), 1); + assert_eq!( + query_pending_operations.operations[0].operation_type, + OperationType::CoreumToXRPLTransfer { + issuer: bridge_xrpl_address.to_owned(), + currency: coreum_originated_token.xrpl_currency.to_owned(), + amount: amount_truncated_and_converted, + recipient: xrpl_receiver_address.to_owned(), + } + ); + + // Send successfull evidence to remove from queue (tokens should be released on XRPL to the receiver) + wasm.execute::( + &contract_addr, + &ExecuteMsg::SaveEvidence { + evidence: Evidence::XRPLTransactionResult { + tx_hash: Some(generate_hash()), + account_sequence: query_pending_operations.operations[0].account_sequence, + ticket_sequence: query_pending_operations.operations[0].ticket_sequence, + transaction_result: TransactionResult::Accepted, + operation_result: OperationResult::CoreumToXRPLTransfer {}, + }, + }, + &vec![], + relayer_account, + ) + .unwrap(); + + let query_pending_operations = wasm + .query::( + &contract_addr, + &QueryMsg::PendingOperations {}, + ) + .unwrap(); + + assert_eq!(query_pending_operations.operations.len(), 0); + // Test sending the amount back from XRPL to Coreum - let amount_to_send_back = Uint128::new(1); + // 100000 (1e5) is the minimum we can send back (15 - 10 (sending precision)) + let amount_to_send_back = Uint128::new(100000); // If we send the token with a different issuer (not multisig address) it should fail let transfer_error = wasm @@ -1788,6 +2070,30 @@ mod tests { .to_string() .contains(ContractError::TokenNotRegistered {}.to_string().as_str())); + // Sending under the minimum should fail (minimum - 1) + let transfer_error = wasm + .execute::( + &contract_addr, + &ExecuteMsg::SaveEvidence { + evidence: Evidence::XRPLToCoreumTransfer { + tx_hash: generate_hash(), + issuer: bridge_xrpl_address.to_owned(), + currency: coreum_originated_token.xrpl_currency.to_owned(), + amount: amount_to_send_back.checked_sub(Uint128::one()).unwrap(), + recipient: Addr::unchecked(sender.address()), + }, + }, + &[], + relayer_account, + ) + .unwrap_err(); + + assert!(transfer_error.to_string().contains( + ContractError::AmountSentIsZeroAfterTruncation {} + .to_string() + .as_str() + )); + // Sending the right evidence should move tokens from the contract to the sender's account wasm.execute::( &contract_addr, @@ -1816,9 +2122,9 @@ mod tests { assert_eq!( request_balance.balance, initial_amount - .checked_sub(amount_to_send) + .checked_sub(amount_to_send) // initial amount .unwrap() - .checked_add(amount_to_send_back) + .checked_add(Uint128::new(10000000000)) // Amount that we sent back after conversion (1e10), the minimum .unwrap() .to_string() ); @@ -1833,7 +2139,7 @@ mod tests { assert_eq!( request_balance.balance, amount_to_send - .checked_sub(amount_to_send_back) + .checked_sub(Uint128::new(10000000000)) .unwrap() .to_string() ); @@ -2289,7 +2595,8 @@ mod tests { ) .unwrap(); - let amount_to_send = Uint128::new(1000000); + let amount_to_send = Uint128::new(1000000); // 1e6 -> truncate -> 1e6 -> decimal conversion -> 1e15 + // Bridge the token to the xrpl receiver address and check pending operations wasm.execute::( &contract_addr, @@ -2339,7 +2646,7 @@ mod tests { operation_type: OperationType::CoreumToXRPLTransfer { issuer: multisig_address, currency: coreum_originated_token.xrpl_currency.to_owned(), - amount: amount_to_send, + amount: amount_to_send.checked_mul(Uint128::new(10u128.pow(9))).unwrap(), // XRPL Decimals - Coreum Decimals -> (15 - 6) = 9 recipient: xrpl_receiver_address, }, } @@ -3218,6 +3525,24 @@ mod tests { // Test sending token 2 with medium precision + // Sending under sending precision would return error because it will be truncated to 0. + let precision_error = wasm + .execute::( + &contract_addr, + &ExecuteMsg::SendToXRPL { + recipient: generate_xrpl_address(), + }, + &coins(100000, denom2.to_owned()), + &signer, + ) + .unwrap_err(); + + assert!(precision_error.to_string().contains( + ContractError::AmountSentIsZeroAfterTruncation {} + .to_string() + .as_str() + )); + // Sending 3990000 would work as it is the maximum bridgable amount wasm.execute::( &contract_addr, diff --git a/integration-tests/coreum/contract_client_test.go b/integration-tests/coreum/contract_client_test.go index 605d5150..b061719e 100644 --- a/integration-tests/coreum/contract_client_test.go +++ b/integration-tests/coreum/contract_client_test.go @@ -827,11 +827,13 @@ func TestSendFromXRPLToCoreumCoreumOriginatedToken(t *testing.T) { require.Equal(t, coinToSend.String(), contractBalanceRes.Balance.String()) // create an evidence of transfer tokens from XRPL to Coreum + // account has 100_000_000_000 in XRPL after conversion xrplToCoreumTransferEvidence := coreum.XRPLToCoreumTransferEvidence{ - TxHash: genXRPLTxHash(t), - Issuer: bridgeXRPLAddress, - Currency: registeredCoreumToken.XRPLCurrency, - Amount: sdkmath.NewInt(4), + TxHash: genXRPLTxHash(t), + Issuer: bridgeXRPLAddress, + Currency: registeredCoreumToken.XRPLCurrency, + // Equivalent of sending 4 tokens back + Amount: sdkmath.NewInt(40_000_000_000), Recipient: coreumRecipient, } @@ -857,7 +859,7 @@ func TestSendFromXRPLToCoreumCoreumOriginatedToken(t *testing.T) { Denom: registeredCoreumToken.Denom, }) require.NoError(t, err) - require.Equal(t, xrplToCoreumTransferEvidence.Amount.String(), recipientBalanceRes.Balance.Amount.String()) + require.Equal(t, sdkmath.NewInt(4).String(), recipientBalanceRes.Balance.Amount.String()) // check contract balance contractBalanceRes, err = bankClient.Balance(ctx, &banktypes.QueryBalanceRequest{ @@ -865,7 +867,7 @@ func TestSendFromXRPLToCoreumCoreumOriginatedToken(t *testing.T) { Denom: denom, }) require.NoError(t, err) - require.Equal(t, coinToSend.Amount.Sub(xrplToCoreumTransferEvidence.Amount).String(), contractBalanceRes.Balance.Amount.String()) + require.Equal(t, coinToSend.Amount.Sub(sdkmath.NewInt(4)).String(), contractBalanceRes.Balance.Amount.String()) } //nolint:tparallel // the test is parallel, but test cases are not @@ -1024,12 +1026,15 @@ func TestSendFromXRPLToCoreumCoreumOriginatedTokenWithFreezingAndWhitelisting(t require.NoError(t, err) require.Equal(t, coinToSend.String(), contractBalanceRes.Balance.String()) + // The amount is the converted amount that was sent in XRPL and is the equivalent of 10_000 in Coreum + amountToSendBack := sdkmath.NewInt(1_000_000_000_000_000) + // create an evidence of transfer tokens from XRPL to Coreum xrplToCoreumTransferEvidence := coreum.XRPLToCoreumTransferEvidence{ TxHash: genXRPLTxHash(t), Issuer: bridgeXRPLAddress, Currency: registeredCoreumToken.XRPLCurrency, - Amount: amountToSend, + Amount: amountToSendBack, Recipient: coreumRecipient, } @@ -1105,6 +1110,7 @@ func TestSendFromXRPLToCoreumCoreumOriginatedTokenWithDifferentSendingPrecision( maxHoldingAmount sdkmath.Int wantReceivedAmount sdkmath.Int wantIsAmountSentIsZeroAfterTruncationError bool + xrplSendingAmount sdkmath.Int }{ { name: "positive_precision_no_truncation", @@ -1113,6 +1119,7 @@ func TestSendFromXRPLToCoreumCoreumOriginatedTokenWithDifferentSendingPrecision( maxHoldingAmount: highMaxHoldingAmount, sendingAmount: integrationtests.ConvertStringWithDecimalsToSDKInt(t, "9999999999.15", 6), wantReceivedAmount: integrationtests.ConvertStringWithDecimalsToSDKInt(t, "9999999999.15", 6), + xrplSendingAmount: sdkmath.NewIntWithDecimal(999999999915, 13), }, { name: "positive_precision_with_truncation", @@ -1121,13 +1128,15 @@ func TestSendFromXRPLToCoreumCoreumOriginatedTokenWithDifferentSendingPrecision( maxHoldingAmount: highMaxHoldingAmount, sendingAmount: integrationtests.ConvertStringWithDecimalsToSDKInt(t, "0.15567", 20), wantReceivedAmount: integrationtests.ConvertStringWithDecimalsToSDKInt(t, "0.15", 20), + xrplSendingAmount: sdkmath.NewIntWithDecimal(15, 13), }, { - name: "positive_precision_low_amount", - sendingPrecision: 2, - decimals: 13, - maxHoldingAmount: highMaxHoldingAmount, - sendingAmount: integrationtests.ConvertStringWithDecimalsToSDKInt(t, "0.009999", 13), + name: "positive_precision_low_amount", + sendingPrecision: 2, + decimals: 13, + maxHoldingAmount: highMaxHoldingAmount, + sendingAmount: integrationtests.ConvertStringWithDecimalsToSDKInt(t, "0.009999", 13), + xrplSendingAmount: sdkmath.NewIntWithDecimal(9999, 8), wantIsAmountSentIsZeroAfterTruncationError: true, }, { @@ -1137,6 +1146,7 @@ func TestSendFromXRPLToCoreumCoreumOriginatedTokenWithDifferentSendingPrecision( maxHoldingAmount: highMaxHoldingAmount, sendingAmount: integrationtests.ConvertStringWithDecimalsToSDKInt(t, "9999999999", 11), wantReceivedAmount: integrationtests.ConvertStringWithDecimalsToSDKInt(t, "9999999999", 11), + xrplSendingAmount: sdkmath.NewIntWithDecimal(9999999999, 15), }, { name: "zero_precision_with_truncation", @@ -1145,13 +1155,15 @@ func TestSendFromXRPLToCoreumCoreumOriginatedTokenWithDifferentSendingPrecision( maxHoldingAmount: highMaxHoldingAmount, sendingAmount: integrationtests.ConvertStringWithDecimalsToSDKInt(t, "1.15567", 1), wantReceivedAmount: integrationtests.ConvertStringWithDecimalsToSDKInt(t, "1", 1), + xrplSendingAmount: sdkmath.NewIntWithDecimal(1, 15), }, { - name: "zero_precision_low_amount", - sendingPrecision: 0, - decimals: 2, - maxHoldingAmount: highMaxHoldingAmount, - sendingAmount: integrationtests.ConvertStringWithDecimalsToSDKInt(t, "0.9999", 2), + name: "zero_precision_low_amount", + sendingPrecision: 0, + decimals: 2, + maxHoldingAmount: highMaxHoldingAmount, + sendingAmount: integrationtests.ConvertStringWithDecimalsToSDKInt(t, "0.9999", 2), + xrplSendingAmount: sdkmath.NewIntWithDecimal(9999, 11), wantIsAmountSentIsZeroAfterTruncationError: true, }, { @@ -1161,6 +1173,7 @@ func TestSendFromXRPLToCoreumCoreumOriginatedTokenWithDifferentSendingPrecision( maxHoldingAmount: highMaxHoldingAmount, sendingAmount: integrationtests.ConvertStringWithDecimalsToSDKInt(t, "9999999900", 3), wantReceivedAmount: integrationtests.ConvertStringWithDecimalsToSDKInt(t, "9999999900", 3), + xrplSendingAmount: sdkmath.NewIntWithDecimal(9999999900, 15), }, { name: "negative_precision_with_truncation", @@ -1169,13 +1182,15 @@ func TestSendFromXRPLToCoreumCoreumOriginatedTokenWithDifferentSendingPrecision( maxHoldingAmount: highMaxHoldingAmount, sendingAmount: integrationtests.ConvertStringWithDecimalsToSDKInt(t, "9999.15567", 20), wantReceivedAmount: integrationtests.ConvertStringWithDecimalsToSDKInt(t, "9900", 20), + xrplSendingAmount: sdkmath.NewIntWithDecimal(9900, 15), }, { - name: "negative_precision_low_amount", - sendingPrecision: -2, - decimals: 6, - maxHoldingAmount: highMaxHoldingAmount, - sendingAmount: integrationtests.ConvertStringWithDecimalsToSDKInt(t, "99.9999", 6), + name: "negative_precision_low_amount", + sendingPrecision: -2, + decimals: 6, + maxHoldingAmount: highMaxHoldingAmount, + sendingAmount: integrationtests.ConvertStringWithDecimalsToSDKInt(t, "99.9999", 6), + xrplSendingAmount: sdkmath.NewIntWithDecimal(999999, 11), wantIsAmountSentIsZeroAfterTruncationError: true, }, } @@ -1221,7 +1236,7 @@ func TestSendFromXRPLToCoreumCoreumOriginatedTokenWithDifferentSendingPrecision( TxHash: genXRPLTxHash(t), Issuer: bridgeXRPLAddress, Currency: registeredCoreumToken.XRPLCurrency, - Amount: tt.sendingAmount, + Amount: tt.xrplSendingAmount, Recipient: coreumRecipient, } @@ -1928,7 +1943,8 @@ func TestSendFromCoreumToXRPLCoreumOriginatedToken(t *testing.T) { require.NotNil(t, operationType) require.Equal(t, operationType.Issuer, bridgeXRPLAddress) require.Equal(t, operationType.Currency, registeredCoreumOriginatedToken1.XRPLCurrency) - require.Equal(t, operationType.Amount, amountToSendOfToken1) + // XRPL DECIMALS (15) - TOKEN DECIMALS (5) = 10 + require.Equal(t, operationType.Amount, amountToSendOfToken1.Mul(sdk.NewInt(10_000_000_000))) require.Equal(t, operationType.Recipient, xrplRecipientAddress.String()) acceptedTxEvidence := coreum.XRPLTransactionResultCoreumToXRPLTransferEvidence{ @@ -1977,7 +1993,8 @@ func TestSendFromCoreumToXRPLCoreumOriginatedToken(t *testing.T) { require.NotNil(t, operationType) require.Equal(t, operationType.Issuer, bridgeXRPLAddress) require.Equal(t, operationType.Currency, registeredCoreumOriginatedToken2.XRPLCurrency) - require.Equal(t, operationType.Amount, amountToSendOfToken2) + // XRPL DECIMALS (15) - TOKEN DECIMALS (6) = 9 + require.Equal(t, operationType.Amount, amountToSendOfToken2.Mul(sdkmath.NewIntWithDecimal(1, 9))) require.Equal(t, operationType.Recipient, xrplRecipientAddress.String()) acceptedTxEvidence = coreum.XRPLTransactionResultCoreumToXRPLTransferEvidence{ @@ -2054,7 +2071,7 @@ func TestSendFromCoreumToXRPLCoreumOriginatedTokenWithDifferentSendingPrecisionA decimals: 6, maxHoldingAmount: highMaxHoldingAmount, sendingAmount: integrationtests.ConvertStringWithDecimalsToSDKInt(t, "9999999999.15", 6), - wantReceivedAmount: integrationtests.ConvertStringWithDecimalsToSDKInt(t, "9999999999.15", 6), + wantReceivedAmount: integrationtests.ConvertStringWithDecimalsToSDKInt(t, "9999999999.15", 15), }, { name: "positive_precision_with_truncation", @@ -2062,7 +2079,7 @@ func TestSendFromCoreumToXRPLCoreumOriginatedTokenWithDifferentSendingPrecisionA decimals: 20, maxHoldingAmount: highMaxHoldingAmount, sendingAmount: integrationtests.ConvertStringWithDecimalsToSDKInt(t, "0.15567", 20), - wantReceivedAmount: integrationtests.ConvertStringWithDecimalsToSDKInt(t, "0.15", 20), + wantReceivedAmount: integrationtests.ConvertStringWithDecimalsToSDKInt(t, "0.15", 15), }, { name: "positive_precision_low_amount", @@ -2078,7 +2095,7 @@ func TestSendFromCoreumToXRPLCoreumOriginatedTokenWithDifferentSendingPrecisionA decimals: 11, maxHoldingAmount: highMaxHoldingAmount, sendingAmount: integrationtests.ConvertStringWithDecimalsToSDKInt(t, "9999999999", 11), - wantReceivedAmount: integrationtests.ConvertStringWithDecimalsToSDKInt(t, "9999999999", 11), + wantReceivedAmount: integrationtests.ConvertStringWithDecimalsToSDKInt(t, "9999999999", 15), }, { name: "zero_precision_with_truncation", @@ -2086,7 +2103,7 @@ func TestSendFromCoreumToXRPLCoreumOriginatedTokenWithDifferentSendingPrecisionA decimals: 1, maxHoldingAmount: highMaxHoldingAmount, sendingAmount: integrationtests.ConvertStringWithDecimalsToSDKInt(t, "1.15567", 1), - wantReceivedAmount: integrationtests.ConvertStringWithDecimalsToSDKInt(t, "1", 1), + wantReceivedAmount: integrationtests.ConvertStringWithDecimalsToSDKInt(t, "1", 15), }, { name: "zero_precision_low_amount", @@ -2102,7 +2119,7 @@ func TestSendFromCoreumToXRPLCoreumOriginatedTokenWithDifferentSendingPrecisionA decimals: 3, maxHoldingAmount: highMaxHoldingAmount, sendingAmount: integrationtests.ConvertStringWithDecimalsToSDKInt(t, "9999999900", 3), - wantReceivedAmount: integrationtests.ConvertStringWithDecimalsToSDKInt(t, "9999999900", 3), + wantReceivedAmount: integrationtests.ConvertStringWithDecimalsToSDKInt(t, "9999999900", 15), }, { name: "negative_precision_with_truncation", @@ -2110,7 +2127,7 @@ func TestSendFromCoreumToXRPLCoreumOriginatedTokenWithDifferentSendingPrecisionA decimals: 20, maxHoldingAmount: highMaxHoldingAmount, sendingAmount: integrationtests.ConvertStringWithDecimalsToSDKInt(t, "9999.15567", 20), - wantReceivedAmount: integrationtests.ConvertStringWithDecimalsToSDKInt(t, "9900", 20), + wantReceivedAmount: integrationtests.ConvertStringWithDecimalsToSDKInt(t, "9900", 15), }, { name: "negative_precision_low_amount", diff --git a/relayer/coreum/contract.go b/relayer/coreum/contract.go index b52c3ede..72c11f0e 100644 --- a/relayer/coreum/contract.go +++ b/relayer/coreum/contract.go @@ -750,22 +750,6 @@ func (c *ContractClient) GetCoreumTokenByDenom(ctx context.Context, denom string return CoreumToken{}, errors.Errorf("token not found in the registered tokens list, denom:%s", denom) } -// GetCoreumTokenByXRPLCurrency returns a coreum registered token or nil by the provided xrpl currency. -func (c *ContractClient) GetCoreumTokenByXRPLCurrency(ctx context.Context, xrplCurrency string) (CoreumToken, error) { - // TODO(dzmitryhil) use new query function from the contract once we create it - tokens, err := c.GetCoreumTokens(ctx) - if err != nil { - return CoreumToken{}, err - } - for _, token := range tokens { - if token.XRPLCurrency == xrplCurrency { - return token, nil - } - } - - return CoreumToken{}, errors.Errorf("token not found in the registered tokens list, xrplCurrency:%s", xrplCurrency) -} - // GetCoreumTokens returns a list of all coreum tokens. func (c *ContractClient) GetCoreumTokens(ctx context.Context) ([]CoreumToken, error) { tokens := make([]CoreumToken, 0) diff --git a/relayer/processes/amount.go b/relayer/processes/amount.go index d2b4b944..11b650c5 100644 --- a/relayer/processes/amount.go +++ b/relayer/processes/amount.go @@ -22,9 +22,9 @@ const ( XRPCurrency = "XRP" ) -// ConvertXRPLOriginatedTokenXRPLAmountToCoreumAmount converts the XRPL native token amount from XRPL to coreum amount +// ConvertXRPLAmountToCoreumAmount converts the XRPL native token amount from XRPL to coreum amount // based on the currency type. -func ConvertXRPLOriginatedTokenXRPLAmountToCoreumAmount(xrplAmount rippledata.Amount) (sdkmath.Int, error) { +func ConvertXRPLAmountToCoreumAmount(xrplAmount rippledata.Amount) (sdkmath.Int, error) { if xrplAmount.Value == nil { return sdkmath.ZeroInt(), nil } @@ -55,16 +55,6 @@ func ConvertXRPLOriginatedTokenCoreumAmountToXRPLAmount(coreumAmount sdkmath.Int return convertCoreumAmountToXRPLAmountWithDecimals(coreumAmount, XRPLIssuedCurrencyDecimals, issuerString, currencyString) } -// ConvertCoreumOriginatedTokenXRPLAmountToCoreumAmount converts the coreum originated token XRPL amount to coreum amount based on decimals. -func ConvertCoreumOriginatedTokenXRPLAmountToCoreumAmount(xrplAmount rippledata.Amount, decimals uint32) (sdkmath.Int, error) { - return convertXRPLAmountToCoreumAmountWithDecimals(xrplAmount, decimals) -} - -// ConvertCoreumOriginatedTokenCoreumAmountToXRPLAmount converts the coreum originated token amount to XRPL amount based on decimals. -func ConvertCoreumOriginatedTokenCoreumAmountToXRPLAmount(coreumAmount sdkmath.Int, decimals uint32, issuerString, currencyString string) (rippledata.Amount, error) { - return convertCoreumAmountToXRPLAmountWithDecimals(coreumAmount, decimals, issuerString, currencyString) -} - func convertXRPLAmountToCoreumAmountWithDecimals(xrplAmount rippledata.Amount, decimals uint32) (sdkmath.Int, error) { xrplRatAmount := xrplAmount.Value.Rat() // not XRP value is repressed as value multiplied by 1e15 diff --git a/relayer/processes/amount_test.go b/relayer/processes/amount_test.go index 8ce38d38..6f06ec39 100644 --- a/relayer/processes/amount_test.go +++ b/relayer/processes/amount_test.go @@ -12,7 +12,7 @@ import ( "github.com/CoreumFoundation/coreumbridge-xrpl/relayer/xrpl" ) -func TestConvertXRPLOriginatedTokenXRPLAmountToCoreumAmount(t *testing.T) { +func TestConvertXRPLAmountToCoreumAmount(t *testing.T) { t.Parallel() var ( @@ -81,7 +81,7 @@ func TestConvertXRPLOriginatedTokenXRPLAmountToCoreumAmount(t *testing.T) { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() - got, err := processes.ConvertXRPLOriginatedTokenXRPLAmountToCoreumAmount(tt.xrplAmount) + got, err := processes.ConvertXRPLAmountToCoreumAmount(tt.xrplAmount) if tt.wantErr { require.Error(t, err) } else { @@ -187,140 +187,6 @@ func TestConvertXRPLOriginatedTokenCoreumAmountToXRPLAmount(t *testing.T) { } } -func TestConvertCoreumOriginatedTokenXRPLAmountToCoreumAmount(t *testing.T) { - t.Parallel() - - var ( - fooIssuer = xrpl.GenPrivKeyTxSigner().Account().String() - fooCurrency = "FOO" - ) - - tests := []struct { - name string - xrplAmount rippledata.Amount - decimals uint32 - want sdkmath.Int - wantErr bool - }{ - { - name: "one_XRPL_FOO_to_coreum_FOO", - xrplAmount: amountStringToXRPLAmount(t, fmt.Sprintf("1.0/%s/%s", fooCurrency, fooIssuer)), - decimals: 10, - want: stringToSDKInt(t, "10000000000"), - }, - { - name: "one_with_some_decimals_XRPL_FOO_to_coreum_FOO", - xrplAmount: amountStringToXRPLAmount(t, fmt.Sprintf("1.00000000101/%s/%s", fooCurrency, fooIssuer)), - decimals: 10, - want: sdkmath.NewIntFromUint64(10000000010), - }, - { - name: "min_decimals_XRPL_FOO_to_coreum_FOO", - xrplAmount: amountStringToXRPLAmount(t, fmt.Sprintf("0.000000000000001/%s/%s", fooCurrency, fooIssuer)), - decimals: 15, - want: sdkmath.NewIntFromUint64(1), - }, - { - name: "high_value_XRPL_FOO_to_coreum_FOO_with_high_decimals", - xrplAmount: amountStringToXRPLAmount(t, fmt.Sprintf("1.1e10/%s/%s", fooCurrency, fooIssuer)), - decimals: 20, - want: stringToSDKInt(t, "1100000000000000000000000000000"), - }, - { - name: "invalid_foo_amount", - xrplAmount: amountStringToXRPLAmount(t, fmt.Sprintf("1e92/%s/%s", fooCurrency, fooIssuer)), - decimals: 15, - wantErr: true, - }, - } - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - got, err := processes.ConvertCoreumOriginatedTokenXRPLAmountToCoreumAmount(tt.xrplAmount, tt.decimals) - if tt.wantErr { - require.Error(t, err) - } else { - require.NoError(t, err) - } - require.Equal(t, tt.want.String(), got.String()) - }) - } -} - -func TestConvertCoreumOriginatedTokenCoreumAmountToXRPLAmount(t *testing.T) { - t.Parallel() - - var ( - fooIssuer = xrpl.GenPrivKeyTxSigner().Account().String() - fooCurrency = "FOO" - ) - - tests := []struct { - name string - coreumAmount sdkmath.Int - decimals uint32 - issuer string - currency string - want rippledata.Amount - wantErr bool - }{ - { - name: "one_coreum_FOO_to_XRPL_FOO", - coreumAmount: sdkmath.NewIntFromUint64(1000000000000000), - decimals: 15, - issuer: fooIssuer, - currency: fooCurrency, - want: amountStringToXRPLAmount(t, fmt.Sprintf("1.0/%s/%s", fooCurrency, fooIssuer)), - }, - { - name: "one_with_some_decimals_FOO_to_XRPL_FOO", - coreumAmount: sdkmath.NewIntFromUint64(1000000000100000), - decimals: 6, - issuer: fooIssuer, - currency: fooCurrency, - want: amountStringToXRPLAmount(t, fmt.Sprintf("1000000000.1/%s/%s", fooCurrency, fooIssuer)), - }, - { - name: "min_decimals_FOO_to_XRPL_FOO", - coreumAmount: sdkmath.NewIntFromUint64(1), - decimals: 15, - issuer: fooIssuer, - currency: fooCurrency, - want: amountStringToXRPLAmount(t, fmt.Sprintf("0.000000000000001/%s/%s", fooCurrency, fooIssuer)), - }, - { - name: "high_value_FOO_to_XRPL_FOO", - coreumAmount: stringToSDKInt(t, "10000000000000000000000000000000000000000"), - decimals: 10, - issuer: fooIssuer, - currency: fooCurrency, - want: amountStringToXRPLAmount(t, fmt.Sprintf("1e30/%s/%s", fooCurrency, fooIssuer)), - }, - { - name: "max_high_value_with_some_decimals_FOO_to_XRPL_FOO", - coreumAmount: stringToSDKInt(t, "1000000000000001"), - decimals: 15, - issuer: fooIssuer, - currency: fooCurrency, - want: amountStringToXRPLAmount(t, fmt.Sprintf("1.000000000000001/%s/%s", fooCurrency, fooIssuer)), - }, - } - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - got, err := processes.ConvertCoreumOriginatedTokenCoreumAmountToXRPLAmount(tt.coreumAmount, tt.decimals, tt.issuer, tt.currency) - if tt.wantErr { - require.Error(t, err) - } else { - require.NoError(t, err) - } - require.Equal(t, tt.want.String(), got.String()) - }) - } -} - func amountStringToXRPLAmount(t *testing.T, amountString string) rippledata.Amount { t.Helper() diff --git a/relayer/processes/model.go b/relayer/processes/model.go index 4b4b66eb..15442768 100644 --- a/relayer/processes/model.go +++ b/relayer/processes/model.go @@ -22,7 +22,6 @@ type ContractClient interface { SaveSignature(ctx context.Context, sender sdk.AccAddress, operationID uint32, signature string) (*sdk.TxResponse, error) GetPendingOperations(ctx context.Context) ([]coreum.Operation, error) GetContractConfig(ctx context.Context) (coreum.ContractConfig, error) - GetCoreumTokenByXRPLCurrency(ctx context.Context, xrplCurrency string) (coreum.CoreumToken, error) } // XRPLAccountTxScanner is XRPL account tx scanner. diff --git a/relayer/processes/model_mocks_test.go b/relayer/processes/model_mocks_test.go index 610056a1..e4f073de 100644 --- a/relayer/processes/model_mocks_test.go +++ b/relayer/processes/model_mocks_test.go @@ -54,21 +54,6 @@ func (mr *MockContractClientMockRecorder) GetContractConfig(arg0 interface{}) *g return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetContractConfig", reflect.TypeOf((*MockContractClient)(nil).GetContractConfig), arg0) } -// GetCoreumTokenByXRPLCurrency mocks base method. -func (m *MockContractClient) GetCoreumTokenByXRPLCurrency(arg0 context.Context, arg1 string) (coreum.CoreumToken, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetCoreumTokenByXRPLCurrency", arg0, arg1) - ret0, _ := ret[0].(coreum.CoreumToken) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetCoreumTokenByXRPLCurrency indicates an expected call of GetCoreumTokenByXRPLCurrency. -func (mr *MockContractClientMockRecorder) GetCoreumTokenByXRPLCurrency(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCoreumTokenByXRPLCurrency", reflect.TypeOf((*MockContractClient)(nil).GetCoreumTokenByXRPLCurrency), arg0, arg1) -} - // GetPendingOperations mocks base method. func (m *MockContractClient) GetPendingOperations(arg0 context.Context) ([]coreum.Operation, error) { m.ctrl.T.Helper() diff --git a/relayer/processes/xrpl_tx_observer.go b/relayer/processes/xrpl_tx_observer.go index 8dfdce23..47ed3cab 100644 --- a/relayer/processes/xrpl_tx_observer.go +++ b/relayer/processes/xrpl_tx_observer.go @@ -4,7 +4,6 @@ import ( "context" "strings" - sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/pkg/errors" rippledata "github.com/rubblelabs/ripple/data" @@ -126,23 +125,10 @@ func (o *XRPLTxObserver) processIncomingTx(ctx context.Context, tx rippledata.Tr deliveredXRPLAmount := tx.MetaData.DeliveredAmount stringCurrency := xrpl.ConvertCurrencyToString(deliveredXRPLAmount.Currency) - var coreumAmount sdkmath.Int - // for the coreum originated tokens we need to use toke decimals, but for the XRPL they are static - if o.cfg.BridgeXRPLAddress.String() == deliveredXRPLAmount.Issuer.String() { - coreumToken, err := o.contractClient.GetCoreumTokenByXRPLCurrency(ctx, stringCurrency) - if err != nil { - return errors.Wrapf(err, "faild to get XRPL token for the XRPL to coreum transfer") - } - coreumAmount, err = ConvertCoreumOriginatedTokenXRPLAmountToCoreumAmount(*deliveredXRPLAmount, coreumToken.Decimals) - if err != nil { - return err - } - } else { - var err error - coreumAmount, err = ConvertXRPLOriginatedTokenXRPLAmountToCoreumAmount(*deliveredXRPLAmount) - if err != nil { - return err - } + + coreumAmount, err := ConvertXRPLAmountToCoreumAmount(*deliveredXRPLAmount) + if err != nil { + return err } if coreumAmount.IsZero() { @@ -158,7 +144,7 @@ func (o *XRPLTxObserver) processIncomingTx(ctx context.Context, tx rippledata.Tr Recipient: coreumRecipient, } - _, err := o.contractClient.SendXRPLToCoreumTransferEvidence(ctx, o.cfg.RelayerCoreumAddress, evidence) + _, err = o.contractClient.SendXRPLToCoreumTransferEvidence(ctx, o.cfg.RelayerCoreumAddress, evidence) if err == nil { return nil } diff --git a/relayer/processes/xrpl_tx_observer_test.go b/relayer/processes/xrpl_tx_observer_test.go index 9ba24780..fb4d6dfd 100644 --- a/relayer/processes/xrpl_tx_observer_test.go +++ b/relayer/processes/xrpl_tx_observer_test.go @@ -145,12 +145,6 @@ func TestXRPLTxObserver_Start(t *testing.T) { contractClientMock := NewMockContractClient(ctrl) stringCurrency := xrpl.ConvertCurrencyToString(xrplOriginatedTokenXRPLAmount.Currency) - tokenDecimals := uint32(10) - contractClientMock.EXPECT().GetCoreumTokenByXRPLCurrency(gomock.Any(), stringCurrency). - Return(coreum.CoreumToken{ - Decimals: tokenDecimals, - }, nil) - contractClientMock.EXPECT().SendXRPLToCoreumTransferEvidence( gomock.Any(), relayerAddress, @@ -158,7 +152,7 @@ func TestXRPLTxObserver_Start(t *testing.T) { TxHash: rippledata.Hash256{}.String(), Issuer: bridgeXRPLAddress.String(), Currency: stringCurrency, - Amount: sdkmath.NewIntWithDecimal(999, int(tokenDecimals)), + Amount: sdkmath.NewIntWithDecimal(999, int(processes.XRPLIssuedCurrencyDecimals)), Recipient: coreumRecipientAddress, }, ).Return(nil, nil) diff --git a/relayer/processes/xrpl_tx_submitter.go b/relayer/processes/xrpl_tx_submitter.go index 17584a86..66ec4861 100644 --- a/relayer/processes/xrpl_tx_submitter.go +++ b/relayer/processes/xrpl_tx_submitter.go @@ -279,7 +279,7 @@ func (s *XRPLTxSubmitter) buildSubmittableTransaction( SigningPubKey: &xrplPubKey, }, } - tx, err := s.buildXRPLTxFromOperation(ctx, operation) + tx, err := s.buildXRPLTxFromOperation(operation) if err != nil { return nil, false, err } @@ -313,7 +313,7 @@ func (s *XRPLTxSubmitter) buildSubmittableTransaction( return nil, false, nil } // build tx one more time to be sure that it is not affected - tx, err := s.buildXRPLTxFromOperation(ctx, operation) + tx, err := s.buildXRPLTxFromOperation(operation) if err != nil { return nil, false, err } @@ -379,7 +379,7 @@ func (s *XRPLTxSubmitter) preValidateOperation(ctx context.Context, operation co } func (s *XRPLTxSubmitter) registerTxSignature(ctx context.Context, operation coreum.Operation) error { - tx, err := s.buildXRPLTxFromOperation(ctx, operation) + tx, err := s.buildXRPLTxFromOperation(operation) if err != nil { return err } @@ -403,22 +403,13 @@ func (s *XRPLTxSubmitter) registerTxSignature(ctx context.Context, operation cor return errors.Wrap(err, "failed to register transaction signature") } -func (s *XRPLTxSubmitter) buildXRPLTxFromOperation(ctx context.Context, operation coreum.Operation) (MultiSignableTransaction, error) { +func (s *XRPLTxSubmitter) buildXRPLTxFromOperation(operation coreum.Operation) (MultiSignableTransaction, error) { switch { case isAllocateTicketsOperation(operation): return BuildTicketCreateTxForMultiSigning(s.cfg.BridgeXRPLAddress, operation) case isTrustSetOperation(operation): return BuildTrustSetTxForMultiSigning(s.cfg.BridgeXRPLAddress, operation) case isCoreumToXRPLTransfer(operation): - // for the coreum originated tokens we need to fetch token decimals, but for the XRPL they are static - operationType := operation.OperationType.CoreumToXRPLTransfer - if s.cfg.BridgeXRPLAddress.String() == operationType.Issuer { - coreumToken, err := s.contractClient.GetCoreumTokenByXRPLCurrency(ctx, operationType.Currency) - if err != nil { - return nil, errors.Wrapf(err, "faild to get XRPL token for the coreum to XRPL transfer") - } - return BuildCoreumToXRPLCoreumOriginatedTokenTransferPaymentTxForMultiSigning(s.cfg.BridgeXRPLAddress, operation, coreumToken.Decimals) - } return BuildCoreumToXRPLXRPLOriginatedTokenTransferPaymentTxForMultiSigning(s.cfg.BridgeXRPLAddress, operation) default: return nil, errors.Errorf("failed to process operation, unable to determine operation type, operation:%+v", operation) diff --git a/relayer/processes/xrpl_tx_submitter_operation_tx.go b/relayer/processes/xrpl_tx_submitter_operation_tx.go index e12b6117..521eca95 100644 --- a/relayer/processes/xrpl_tx_submitter_operation_tx.go +++ b/relayer/processes/xrpl_tx_submitter_operation_tx.go @@ -90,12 +90,10 @@ func BuildCoreumToXRPLXRPLOriginatedTokenTransferPaymentTxForMultiSigning(bridge func BuildCoreumToXRPLCoreumOriginatedTokenTransferPaymentTxForMultiSigning( bridgeXRPLAddress rippledata.Account, operation coreum.Operation, - decimals uint32, ) (*rippledata.Payment, error) { coreumToXRPLTransferOperationType := operation.OperationType.CoreumToXRPLTransfer - value, err := ConvertCoreumOriginatedTokenCoreumAmountToXRPLAmount( + value, err := ConvertXRPLOriginatedTokenCoreumAmountToXRPLAmount( coreumToXRPLTransferOperationType.Amount, - decimals, coreumToXRPLTransferOperationType.Issuer, coreumToXRPLTransferOperationType.Currency, ) diff --git a/relayer/processes/xrpl_tx_submitter_test.go b/relayer/processes/xrpl_tx_submitter_test.go index 5639afcb..9bdfd123 100644 --- a/relayer/processes/xrpl_tx_submitter_test.go +++ b/relayer/processes/xrpl_tx_submitter_test.go @@ -40,17 +40,9 @@ func TestXRPLTxSubmitter_Start(t *testing.T) { // ********** CoreumToXRPLTransfer ********** - // XRPLOriginated - - coreumToXRPLXRPLOriginatedTokenTransferOperation, - coreumToXRPLXRPLOriginatedTokenTransferOperationWithSignatures, - coreumToXRPLXRPLOriginatedTokenTransferOperationValidSigners := buildCoreumToXRPLXRPLOriginatedTokenTransferTestData(t, xrplTxSigners, bridgeXRPLAddress, contractRelayers) - - // CoreumOriginated - coreumOriginatedTokenDecimals := uint32(6) - coreumToXRPLCoreumOriginatedTokenTransferOperation, - coreumToXRPLCoreumOriginatedTokenTransferOperationWithSignatures, - coreumToXRPLCoreumOriginatedTokenTransferOperationValidSigners := buildCoreumToXRPLCoreumOriginatedTokenTransferTestData(t, xrplTxSigners, bridgeXRPLAddress, contractRelayers, coreumOriginatedTokenDecimals) + coreumToXRPLTokenTransferOperation, + coreumToXRPLTokenTransferOperationWithSignatures, + coreumToXRPLTokenTransferOperationValidSigners := buildCoreumToXRPLTokenTransferTestData(t, xrplTxSigners, bridgeXRPLAddress, contractRelayers) tests := []struct { name string @@ -197,14 +189,14 @@ func TestXRPLTxSubmitter_Start(t *testing.T) { }, }, { - name: "register_signature_for_coreum_to_XRPL_XRPL_originated_token_transfer_payment_tx", + name: "register_signature_for_coreum_to_XRPL_token_transfer_payment_tx", contractClientBuilder: func(ctrl *gomock.Controller) processes.ContractClient { contractClientMock := NewMockContractClient(ctrl) - contractClientMock.EXPECT().GetPendingOperations(gomock.Any()).Return([]coreum.Operation{coreumToXRPLXRPLOriginatedTokenTransferOperation}, nil) + contractClientMock.EXPECT().GetPendingOperations(gomock.Any()).Return([]coreum.Operation{coreumToXRPLTokenTransferOperation}, nil) contractClientMock.EXPECT().GetContractConfig(gomock.Any()).Return(coreum.ContractConfig{ Relayers: contractRelayers, }, nil) - contractClientMock.EXPECT().SaveSignature(gomock.Any(), contractRelayers[0].CoreumAddress, coreumToXRPLXRPLOriginatedTokenTransferOperation.TicketSequence, coreumToXRPLXRPLOriginatedTokenTransferOperationValidSigners[0].Signer.TxnSignature.String()) + contractClientMock.EXPECT().SaveSignature(gomock.Any(), contractRelayers[0].CoreumAddress, coreumToXRPLTokenTransferOperation.TicketSequence, coreumToXRPLTokenTransferOperationValidSigners[0].Signer.TxnSignature.String()) return contractClientMock }, xrplRPCClientBuilder: func(ctrl *gomock.Controller) processes.XRPLRPCClient { @@ -214,18 +206,18 @@ func TestXRPLTxSubmitter_Start(t *testing.T) { }, xrplTxSignerBuilder: func(ctrl *gomock.Controller) processes.XRPLTxSigner { xrplTxSignerMock := NewMockXRPLTxSigner(ctrl) - tx, err := processes.BuildCoreumToXRPLXRPLOriginatedTokenTransferPaymentTxForMultiSigning(bridgeXRPLAddress, coreumToXRPLXRPLOriginatedTokenTransferOperation) + tx, err := processes.BuildCoreumToXRPLXRPLOriginatedTokenTransferPaymentTxForMultiSigning(bridgeXRPLAddress, coreumToXRPLTokenTransferOperation) require.NoError(t, err) - xrplTxSignerMock.EXPECT().MultiSign(tx, xrplTxSignerKeyName).Return(coreumToXRPLXRPLOriginatedTokenTransferOperationValidSigners[0], nil) + xrplTxSignerMock.EXPECT().MultiSign(tx, xrplTxSignerKeyName).Return(coreumToXRPLTokenTransferOperationValidSigners[0], nil) return xrplTxSignerMock }, }, { - name: "submit_coreum_to_XRPL_XRPL_originated_token_transfer_payment_tx_with_filtered_signature", + name: "submit_coreum_to_XRPL_token_transfer_payment_tx_with_filtered_signature", contractClientBuilder: func(ctrl *gomock.Controller) processes.ContractClient { contractClientMock := NewMockContractClient(ctrl) - contractClientMock.EXPECT().GetPendingOperations(gomock.Any()).Return([]coreum.Operation{coreumToXRPLXRPLOriginatedTokenTransferOperationWithSignatures}, nil) + contractClientMock.EXPECT().GetPendingOperations(gomock.Any()).Return([]coreum.Operation{coreumToXRPLTokenTransferOperationWithSignatures}, nil) contractClientMock.EXPECT().GetContractConfig(gomock.Any()).Return(coreum.ContractConfig{ Relayers: contractRelayers, }, nil) @@ -234,70 +226,9 @@ func TestXRPLTxSubmitter_Start(t *testing.T) { xrplRPCClientBuilder: func(ctrl *gomock.Controller) processes.XRPLRPCClient { xrplRPCClientMock := NewMockXRPLRPCClient(ctrl) xrplRPCClientMock.EXPECT().AccountInfo(gomock.Any(), bridgeXRPLAddress).Return(bridgeXRPLSignerAccountWithSigners, nil) - expectedTx, err := processes.BuildCoreumToXRPLXRPLOriginatedTokenTransferPaymentTxForMultiSigning(bridgeXRPLAddress, coreumToXRPLXRPLOriginatedTokenTransferOperationWithSignatures) + expectedTx, err := processes.BuildCoreumToXRPLXRPLOriginatedTokenTransferPaymentTxForMultiSigning(bridgeXRPLAddress, coreumToXRPLTokenTransferOperationWithSignatures) require.NoError(t, err) - require.NoError(t, rippledata.SetSigners(expectedTx, coreumToXRPLXRPLOriginatedTokenTransferOperationValidSigners...)) - xrplRPCClientMock.EXPECT().Submit(gomock.Any(), gomock.Any()).Do(func(ctx context.Context, tx rippledata.Transaction) (xrpl.SubmitResult, error) { - _, expectedTxRaw, err := rippledata.Raw(expectedTx) - require.NoError(t, err) - _, txRaw, err := rippledata.Raw(tx) - require.NoError(t, err) - require.Equal(t, expectedTxRaw, txRaw) - return xrpl.SubmitResult{}, nil - }) - - return xrplRPCClientMock - }, - }, - { - name: "register_signature_for_coreum_to_XRPL_Coreum_originated_token_transfer_payment_tx", - contractClientBuilder: func(ctrl *gomock.Controller) processes.ContractClient { - contractClientMock := NewMockContractClient(ctrl) - contractClientMock.EXPECT().GetPendingOperations(gomock.Any()).Return([]coreum.Operation{coreumToXRPLCoreumOriginatedTokenTransferOperation}, nil) - contractClientMock.EXPECT().GetContractConfig(gomock.Any()).Return(coreum.ContractConfig{ - Relayers: contractRelayers, - }, nil) - contractClientMock.EXPECT().GetCoreumTokenByXRPLCurrency(gomock.Any(), coreumToXRPLCoreumOriginatedTokenTransferOperation.OperationType.CoreumToXRPLTransfer.Currency). - Return(coreum.CoreumToken{ - Decimals: coreumOriginatedTokenDecimals, - }, nil) - contractClientMock.EXPECT().SaveSignature(gomock.Any(), contractRelayers[0].CoreumAddress, coreumToXRPLCoreumOriginatedTokenTransferOperation.TicketSequence, coreumToXRPLCoreumOriginatedTokenTransferOperationValidSigners[0].Signer.TxnSignature.String()) - return contractClientMock - }, - xrplRPCClientBuilder: func(ctrl *gomock.Controller) processes.XRPLRPCClient { - xrplRPCClientMock := NewMockXRPLRPCClient(ctrl) - xrplRPCClientMock.EXPECT().AccountInfo(gomock.Any(), bridgeXRPLAddress).Return(bridgeXRPLSignerAccountWithSigners, nil) - return xrplRPCClientMock - }, - xrplTxSignerBuilder: func(ctrl *gomock.Controller) processes.XRPLTxSigner { - xrplTxSignerMock := NewMockXRPLTxSigner(ctrl) - tx, err := processes.BuildCoreumToXRPLCoreumOriginatedTokenTransferPaymentTxForMultiSigning(bridgeXRPLAddress, coreumToXRPLCoreumOriginatedTokenTransferOperation, coreumOriginatedTokenDecimals) - require.NoError(t, err) - xrplTxSignerMock.EXPECT().MultiSign(tx, xrplTxSignerKeyName).Return(coreumToXRPLCoreumOriginatedTokenTransferOperationValidSigners[0], nil) - - return xrplTxSignerMock - }, - }, - { - name: "submit_coreum_to_XRPL_Coreum_originated_token_transfer_payment_tx_with_filtered_signature", - contractClientBuilder: func(ctrl *gomock.Controller) processes.ContractClient { - contractClientMock := NewMockContractClient(ctrl) - contractClientMock.EXPECT().GetPendingOperations(gomock.Any()).Return([]coreum.Operation{coreumToXRPLCoreumOriginatedTokenTransferOperationWithSignatures}, nil) - contractClientMock.EXPECT().GetContractConfig(gomock.Any()).Return(coreum.ContractConfig{ - Relayers: contractRelayers, - }, nil) - contractClientMock.EXPECT().GetCoreumTokenByXRPLCurrency(gomock.Any(), coreumToXRPLCoreumOriginatedTokenTransferOperationWithSignatures.OperationType.CoreumToXRPLTransfer.Currency). - Return(coreum.CoreumToken{ - Decimals: coreumOriginatedTokenDecimals, - }, nil).Times(3) - return contractClientMock - }, - xrplRPCClientBuilder: func(ctrl *gomock.Controller) processes.XRPLRPCClient { - xrplRPCClientMock := NewMockXRPLRPCClient(ctrl) - xrplRPCClientMock.EXPECT().AccountInfo(gomock.Any(), bridgeXRPLAddress).Return(bridgeXRPLSignerAccountWithSigners, nil) - expectedTx, err := processes.BuildCoreumToXRPLCoreumOriginatedTokenTransferPaymentTxForMultiSigning(bridgeXRPLAddress, coreumToXRPLCoreumOriginatedTokenTransferOperationWithSignatures, coreumOriginatedTokenDecimals) - require.NoError(t, err) - require.NoError(t, rippledata.SetSigners(expectedTx, coreumToXRPLCoreumOriginatedTokenTransferOperationValidSigners...)) + require.NoError(t, rippledata.SetSigners(expectedTx, coreumToXRPLTokenTransferOperationValidSigners...)) xrplRPCClientMock.EXPECT().Submit(gomock.Any(), gomock.Any()).Do(func(ctx context.Context, tx rippledata.Transaction) (xrpl.SubmitResult, error) { _, expectedTxRaw, err := rippledata.Raw(expectedTx) require.NoError(t, err) @@ -464,7 +395,7 @@ func buildTrustSetTestData( return operation, operationWithSignatures, validSigners } -func buildCoreumToXRPLXRPLOriginatedTokenTransferTestData( +func buildCoreumToXRPLTokenTransferTestData( t *testing.T, xrplTxSigners []*xrpl.PrivKeyTxSigner, bridgeXRPLAddress rippledata.Account, @@ -497,43 +428,6 @@ func buildCoreumToXRPLXRPLOriginatedTokenTransferTestData( return operation, operationWithSignatures, validSigners } -func buildCoreumToXRPLCoreumOriginatedTokenTransferTestData( - t *testing.T, - xrplTxSigners []*xrpl.PrivKeyTxSigner, - bridgeXRPLAddress rippledata.Account, - contractRelayers []coreum.Relayer, - decimals uint32, -) ( - coreum.Operation, coreum.Operation, []rippledata.Signer, -) { - operation := coreum.Operation{ - TicketSequence: 1, - Signatures: nil, - OperationType: coreum.OperationType{ - CoreumToXRPLTransfer: &coreum.OperationTypeCoreumToXRPLTransfer{ - // the bridge is issuer of the token - Issuer: bridgeXRPLAddress.String(), - Currency: "TRC", - Amount: sdkmath.NewIntFromUint64(123), - Recipient: xrpl.GenPrivKeyTxSigner().Account().String(), - }, - }, - } - - operationWithSignatures, validSigners := multiSignOperationFromMultipleSignersWithLastInvalidSignature( - t, - operation, - xrplTxSigners, - contractRelayers, - bridgeXRPLAddress, - func(t *testing.T, signer *xrpl.PrivKeyTxSigner, account rippledata.Account, operation coreum.Operation) rippledata.Signer { - return multiSignCoreumToXRPLCoreumOriginatedTokeTransferOperation(t, signer, account, operation, decimals) - }, - ) - - return operation, operationWithSignatures, validSigners -} - func multiSignOperationFromMultipleSignersWithLastInvalidSignature( t *testing.T, operation coreum.Operation, @@ -610,18 +504,3 @@ func multiSignCoreumToXRPLXRPLOriginatedTokeTransferOperation( return signer } - -func multiSignCoreumToXRPLCoreumOriginatedTokeTransferOperation( - t *testing.T, - relayerXRPLSigner *xrpl.PrivKeyTxSigner, - bridgeXRPLAcc rippledata.Account, - operation coreum.Operation, - decimals uint32, -) rippledata.Signer { - tx, err := processes.BuildCoreumToXRPLCoreumOriginatedTokenTransferPaymentTxForMultiSigning(bridgeXRPLAcc, operation, decimals) - require.NoError(t, err) - signer, err := relayerXRPLSigner.MultiSign(tx) - require.NoError(t, err) - - return signer -}