From fdb1e025855323f74b8f05251c68a410bcab8136 Mon Sep 17 00:00:00 2001 From: Roy Yang Date: Sat, 30 Sep 2023 01:10:23 +1300 Subject: [PATCH] feat: size limit for CCM (#4015) Co-authored-by: Daniel Co-authored-by: dandanlen <3168260+dandanlen@users.noreply.github.com> --- Cargo.lock | 1 - api/bin/chainflip-broker-api/Cargo.toml | 1 - api/bin/chainflip-broker-api/src/main.rs | 63 +------ engine/src/witness/eth/vault.rs | 88 +++++---- localnet/init/scripts/start-broker-api.sh | 2 +- .../cf-integration-tests/src/swapping.rs | 12 +- state-chain/chains/src/lib.rs | 57 +++++- .../pallets/cf-ingress-egress/src/lib.rs | 14 +- .../pallets/cf-ingress-egress/src/tests.rs | 16 +- .../pallets/cf-swapping/src/benchmarking.rs | 8 +- state-chain/pallets/cf-swapping/src/lib.rs | 2 +- state-chain/pallets/cf-swapping/src/tests.rs | 170 +++++------------- state-chain/runtime/src/lib.rs | 2 +- .../traits/src/mocks/egress_handler.rs | 6 +- 14 files changed, 178 insertions(+), 264 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b97abb53b70..40b17f9c828 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1394,7 +1394,6 @@ name = "chainflip-broker-api" version = "0.9.3" dependencies = [ "anyhow", - "cf-chains", "chainflip-api", "clap 3.2.25", "futures", diff --git a/api/bin/chainflip-broker-api/Cargo.toml b/api/bin/chainflip-broker-api/Cargo.toml index fd9176412c8..7fd2604a5da 100644 --- a/api/bin/chainflip-broker-api/Cargo.toml +++ b/api/bin/chainflip-broker-api/Cargo.toml @@ -22,7 +22,6 @@ name = "chainflip-broker-api" [dependencies] chainflip-api = { path = "../../lib" } cf-utilities = { package = "utilities", path = "../../../utilities" } -cf-chains = { path = '../../../state-chain/chains', default-features = false } anyhow = "1.0.66" clap = { version = "3.2.23", features = ["derive"] } diff --git a/api/bin/chainflip-broker-api/src/main.rs b/api/bin/chainflip-broker-api/src/main.rs index b8dfd3eca95..574124a31ad 100644 --- a/api/bin/chainflip-broker-api/src/main.rs +++ b/api/bin/chainflip-broker-api/src/main.rs @@ -1,4 +1,3 @@ -use anyhow::anyhow; use cf_utilities::{ task_scope::{task_scope, Scope}, AnyhowRpcError, @@ -11,10 +10,8 @@ use chainflip_api::{ }; use clap::Parser; use futures::FutureExt; -use hex::FromHexError; use jsonrpsee::{core::async_trait, proc_macros::rpc, server::ServerBuilder}; use serde::{Deserialize, Serialize}; -use sp_rpc::number::NumberOrHex; use std::path::PathBuf; use tracing::log; @@ -40,39 +37,6 @@ impl From for BrokerSwapDepositAddress { } } -#[derive(Serialize, Deserialize)] -pub struct BrokerCcmChannelMetadata { - gas_budget: NumberOrHex, - message: String, - cf_parameters: Option, -} - -fn parse_hex_bytes(string: &str) -> Result, FromHexError> { - hex::decode(string.strip_prefix("0x").unwrap_or(string)) -} - -impl TryInto for BrokerCcmChannelMetadata { - type Error = anyhow::Error; - - fn try_into(self) -> Result { - let gas_budget = self - .gas_budget - .try_into() - .map_err(|_| anyhow!("Failed to parse {:?} as gas budget", self.gas_budget))?; - let message = - parse_hex_bytes(&self.message).map_err(|e| anyhow!("Failed to parse message: {e}"))?; - - let cf_parameters = self - .cf_parameters - .map(|parameters| parse_hex_bytes(¶meters)) - .transpose() - .map_err(|e| anyhow!("Failed to parse cf parameters: {e}"))? - .unwrap_or_default(); - - Ok(CcmChannelMetadata { gas_budget, message, cf_parameters }) - } -} - #[rpc(server, client, namespace = "broker")] pub trait Rpc { #[method(name = "registerAccount")] @@ -85,7 +49,7 @@ pub trait Rpc { destination_asset: Asset, destination_address: String, broker_commission_bps: BasisPoints, - channel_metadata: Option, + channel_metadata: Option, ) -> Result; } @@ -122,10 +86,8 @@ impl RpcServer for RpcServerImpl { destination_asset: Asset, destination_address: String, broker_commission_bps: BasisPoints, - channel_metadata: Option, + channel_metadata: Option, ) -> Result { - let channel_metadata = channel_metadata.map(TryInto::try_into).transpose()?; - Ok(self .api .broker_api() @@ -188,24 +150,3 @@ async fn main() -> anyhow::Result<()> { }) .await } - -#[cfg(test)] -mod test { - use super::*; - use cf_utilities::assert_err; - - #[test] - fn test_decoding() { - assert_eq!(parse_hex_bytes("0x00").unwrap(), vec![0]); - assert_eq!(parse_hex_bytes("cf").unwrap(), vec![0xcf]); - assert_eq!( - parse_hex_bytes("0x00112233445566778899aabbccddeeff").unwrap(), - vec![ - 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, - 0xee, 0xff - ] - ); - assert_eq!(parse_hex_bytes("").unwrap(), b""); - assert_err!(parse_hex_bytes("abc")); - } -} diff --git a/engine/src/witness/eth/vault.rs b/engine/src/witness/eth/vault.rs index c28729c4a7a..09bbb915b15 100644 --- a/engine/src/witness/eth/vault.rs +++ b/engine/src/witness/eth/vault.rs @@ -96,25 +96,31 @@ pub fn call_from_event( message, gas_amount, cf_parameters, - }) => Some(RuntimeCall::Swapping(pallet_cf_swapping::Call::ccm_deposit { - source_asset: native_asset, - destination_asset: try_into_primitive(dst_token)?, - deposit_amount: try_into_primitive(amount)?, - destination_address: try_into_encoded_address( - try_into_primitive(dst_chain)?, - dst_address.to_vec(), - )?, - deposit_metadata: CcmDepositMetadata { - source_chain, - source_address: Some(sender.into()), - channel_metadata: CcmChannelMetadata { - message: message.to_vec(), - gas_budget: try_into_primitive(gas_amount)?, - cf_parameters: cf_parameters.0.to_vec(), + }) => + Some(RuntimeCall::Swapping(pallet_cf_swapping::Call::ccm_deposit { + source_asset: native_asset, + destination_asset: try_into_primitive(dst_token)?, + deposit_amount: try_into_primitive(amount)?, + destination_address: try_into_encoded_address( + try_into_primitive(dst_chain)?, + dst_address.to_vec(), + )?, + deposit_metadata: CcmDepositMetadata { + source_chain, + source_address: Some(sender.into()), + channel_metadata: CcmChannelMetadata { + message: message + .to_vec() + .try_into() + .map_err(|_| anyhow!("Failed to deposit CCM: `message` too long."))?, + gas_budget: try_into_primitive(gas_amount)?, + cf_parameters: cf_parameters.0.to_vec().try_into().map_err(|_| { + anyhow!("Failed to deposit CCM: `cf_parameters` too long.") + })?, + }, }, - }, - tx_hash: event.tx_hash.into(), - })), + tx_hash: event.tx_hash.into(), + })), VaultEvents::XcallTokenFilter(XcallTokenFilter { dst_chain, dst_address, @@ -125,27 +131,33 @@ pub fn call_from_event( message, gas_amount, cf_parameters, - }) => Some(RuntimeCall::Swapping(pallet_cf_swapping::Call::ccm_deposit { - source_asset: *(supported_assets - .get(&src_token) - .ok_or(anyhow!("Source token {src_token:?} not found"))?), - destination_asset: try_into_primitive(dst_token)?, - deposit_amount: try_into_primitive(amount)?, - destination_address: try_into_encoded_address( - try_into_primitive(dst_chain)?, - dst_address.to_vec(), - )?, - deposit_metadata: CcmDepositMetadata { - source_chain, - source_address: Some(sender.into()), - channel_metadata: CcmChannelMetadata { - message: message.to_vec(), - gas_budget: try_into_primitive(gas_amount)?, - cf_parameters: cf_parameters.0.to_vec(), + }) => + Some(RuntimeCall::Swapping(pallet_cf_swapping::Call::ccm_deposit { + source_asset: *(supported_assets + .get(&src_token) + .ok_or(anyhow!("Source token {src_token:?} not found"))?), + destination_asset: try_into_primitive(dst_token)?, + deposit_amount: try_into_primitive(amount)?, + destination_address: try_into_encoded_address( + try_into_primitive(dst_chain)?, + dst_address.to_vec(), + )?, + deposit_metadata: CcmDepositMetadata { + source_chain, + source_address: Some(sender.into()), + channel_metadata: CcmChannelMetadata { + message: message + .to_vec() + .try_into() + .map_err(|_| anyhow!("Failed to deposit CCM. Message too long."))?, + gas_budget: try_into_primitive(gas_amount)?, + cf_parameters: cf_parameters.0.to_vec().try_into().map_err(|_| { + anyhow!("Failed to deposit CCM. cf_parameter too long.") + })?, + }, }, - }, - tx_hash: event.tx_hash.into(), - })), + tx_hash: event.tx_hash.into(), + })), VaultEvents::TransferNativeFailedFilter(TransferNativeFailedFilter { recipient, amount, diff --git a/localnet/init/scripts/start-broker-api.sh b/localnet/init/scripts/start-broker-api.sh index ec809cb8aa1..88b52331f56 100755 --- a/localnet/init/scripts/start-broker-api.sh +++ b/localnet/init/scripts/start-broker-api.sh @@ -1,7 +1,7 @@ #!/bin/bash set -e binary_location=$1 -$binary_location/chainflip-broker-api \ +RUST_LOG=debug,jsonrpsee_types::params=trace $binary_location/chainflip-broker-api \ --port=10997 \ --state_chain.ws_endpoint=ws://localhost:9944 \ --state_chain.signing_key_file localnet/init/keys/BROKER_1 > /tmp/chainflip/chainflip-broker-api.log 2>&1 & diff --git a/state-chain/cf-integration-tests/src/swapping.rs b/state-chain/cf-integration-tests/src/swapping.rs index 656f1dd2245..a3f3360284f 100644 --- a/state-chain/cf-integration-tests/src/swapping.rs +++ b/state-chain/cf-integration-tests/src/swapping.rs @@ -301,9 +301,9 @@ fn can_process_ccm_via_swap_deposit_address() { let gas_budget = 100; let deposit_amount = 1_000; let message = CcmChannelMetadata { - message: vec![0u8, 1u8, 2u8, 3u8, 4u8], + message: vec![0u8, 1u8, 2u8, 3u8, 4u8].try_into().unwrap(), gas_budget, - cf_parameters: vec![], + cf_parameters: Default::default(), }; assert_ok!(Swapping::request_swap_deposit_address( @@ -409,13 +409,13 @@ fn can_process_ccm_via_direct_deposit() { let gas_budget = 100; let deposit_amount = 1_000; - let message = CcmDepositMetadata { + let deposit_metadata = CcmDepositMetadata { source_chain: ForeignChain::Ethereum, source_address: Some(ForeignChainAddress::Eth([0xcf; 20].into())), channel_metadata: CcmChannelMetadata { - message: vec![0u8, 1u8, 2u8, 3u8, 4u8], + message: vec![0u8, 1u8, 2u8, 3u8, 4u8].try_into().unwrap(), gas_budget, - cf_parameters: vec![], + cf_parameters: Default::default(), }, }; @@ -424,7 +424,7 @@ fn can_process_ccm_via_direct_deposit() { deposit_amount, destination_asset: Asset::Usdc, destination_address: EncodedAddress::Eth([0x02; 20]), - deposit_metadata: message, + deposit_metadata, tx_hash: Default::default(), })); let current_epoch = Validator::current_epoch(); diff --git a/state-chain/chains/src/lib.rs b/state-chain/chains/src/lib.rs index 5f325a99f2f..9b27f777f48 100644 --- a/state-chain/chains/src/lib.rs +++ b/state-chain/chains/src/lib.rs @@ -11,14 +11,14 @@ use frame_support::{ pallet_prelude::{MaybeSerializeDeserialize, Member}, sp_runtime::{ traits::{AtLeast32BitUnsigned, CheckedSub}, - DispatchError, + BoundedVec, DispatchError, }, Blake2_256, CloneNoBound, DebugNoBound, EqNoBound, Parameter, PartialEqNoBound, RuntimeDebug, StorageHasher, }; use scale_info::TypeInfo; use serde::{Deserialize, Serialize}; -use sp_core::U256; +use sp_core::{ConstU32, U256}; use sp_std::{ cmp::Ord, convert::{Into, TryFrom}, @@ -152,7 +152,7 @@ pub trait ChainCrypto { /// Uniquely identifies a transaction on the incoming direction. type TransactionInId: Member + Parameter + Unpin + BenchmarkValue; - /// Uniquely identifies a transaction on the outoing direction. + /// Uniquely identifies a transaction on the outgoing direction. type TransactionOutId: Member + Parameter + Unpin + BenchmarkValue; type GovKey: Member + Parameter + Copy + BenchmarkValue; @@ -376,17 +376,56 @@ pub enum SwapOrigin { }, } +pub const MAX_CCM_MSG_LENGTH: u32 = 10_000; +pub const MAX_CCM_CF_PARAM_LENGTH: u32 = 1_000; + +pub type CcmMessage = BoundedVec>; +pub type CcmCfParameters = BoundedVec>; + +#[cfg(feature = "std")] +mod bounded_hex { + use super::*; + use sp_core::Get; + + pub fn serialize( + bounded: &BoundedVec, + serializer: S, + ) -> Result { + serializer.serialize_str(&hex::encode(bounded)) + } + + pub fn deserialize<'de, D: serde::Deserializer<'de>, Size: Get>( + deserializer: D, + ) -> Result, D::Error> { + let hex_str = String::deserialize(deserializer)?; + let bytes = + hex::decode(hex_str.trim_start_matches("0x")).map_err(serde::de::Error::custom)?; + BoundedVec::try_from(bytes).map_err(|input| { + serde::de::Error::invalid_length( + input.len(), + &format!("{} bytes", Size::get()).as_str(), + ) + }) + } +} + /// Deposit channel Metadata for Cross-Chain-Message. -#[derive(Clone, Debug, PartialEq, Eq, Encode, Decode, TypeInfo, Serialize, Deserialize)] +#[derive( + Clone, Debug, PartialEq, Eq, Encode, Decode, TypeInfo, Serialize, Deserialize, MaxEncodedLen, +)] pub struct CcmChannelMetadata { /// Call data used after the message is egressed. - #[cfg_attr(feature = "std", serde(with = "hex::serde"))] - pub message: Vec, + #[cfg_attr(feature = "std", serde(with = "bounded_hex"))] + pub message: CcmMessage, /// User funds designated to be used for gas. + #[cfg_attr(feature = "std", serde(with = "cf_utilities::serde_helpers::number_or_hex"))] pub gas_budget: AssetAmount, - /// Additonal parameters for the cross chain message. - #[cfg_attr(feature = "std", serde(with = "hex::serde"))] - pub cf_parameters: Vec, + /// Additional parameters for the cross chain message. + #[cfg_attr( + feature = "std", + serde(with = "bounded_hex", default, skip_serializing_if = "Vec::is_empty") + )] + pub cf_parameters: CcmCfParameters, } #[derive(Clone, Debug, PartialEq, Eq, Encode, Decode, TypeInfo, Serialize, Deserialize)] diff --git a/state-chain/pallets/cf-ingress-egress/src/lib.rs b/state-chain/pallets/cf-ingress-egress/src/lib.rs index 59afc93e291..cd95228e284 100644 --- a/state-chain/pallets/cf-ingress-egress/src/lib.rs +++ b/state-chain/pallets/cf-ingress-egress/src/lib.rs @@ -14,9 +14,9 @@ pub use weights::WeightInfo; use cf_chains::{ address::{AddressConverter, AddressDerivationApi}, - AllBatch, AllBatchError, CcmChannelMetadata, CcmDepositMetadata, Chain, ChannelLifecycleHooks, - DepositChannel, ExecutexSwapAndCall, FetchAssetParams, ForeignChainAddress, SwapOrigin, - TransferAssetParams, + AllBatch, AllBatchError, CcmCfParameters, CcmChannelMetadata, CcmDepositMetadata, CcmMessage, + Chain, ChannelLifecycleHooks, DepositChannel, ExecutexSwapAndCall, FetchAssetParams, + ForeignChainAddress, SwapOrigin, TransferAssetParams, }; use cf_primitives::{ Asset, AssetAmount, BasisPoints, ChannelId, EgressCounter, EgressId, ForeignChain, @@ -61,18 +61,18 @@ impl FetchOrTransfer { } /// Cross-chain messaging requests. -#[derive(RuntimeDebug, Eq, PartialEq, Clone, Encode, Decode, TypeInfo)] +#[derive(RuntimeDebug, Eq, PartialEq, Clone, Encode, Decode, TypeInfo, MaxEncodedLen)] pub(crate) struct CrossChainMessage { pub egress_id: EgressId, pub asset: C::ChainAsset, pub amount: C::ChainAmount, pub destination_address: C::ChainAccount, - pub message: Vec, + pub message: CcmMessage, // The sender of the deposit transaction. pub source_chain: ForeignChain, pub source_address: Option, // Where funds might be returned to if the message fails. - pub cf_parameters: Vec, + pub cf_parameters: CcmCfParameters, pub gas_budget: C::ChainAmount, } @@ -662,7 +662,7 @@ impl, I: 'static> Pallet { ccm.source_chain, ccm.source_address, ccm.gas_budget, - ccm.message, + ccm.message.to_vec(), ) { Ok(api_call) => { let (broadcast_id, _) = T::Broadcaster::threshold_sign_and_broadcast(api_call); diff --git a/state-chain/pallets/cf-ingress-egress/src/tests.rs b/state-chain/pallets/cf-ingress-egress/src/tests.rs index fc086e4f3d6..8a10e59eb0a 100644 --- a/state-chain/pallets/cf-ingress-egress/src/tests.rs +++ b/state-chain/pallets/cf-ingress-egress/src/tests.rs @@ -93,9 +93,9 @@ fn blacklisted_asset_will_not_egress_via_ccm() { source_chain: ForeignChain::Ethereum, source_address: Some(ForeignChainAddress::Eth([0xcf; 20].into())), channel_metadata: CcmChannelMetadata { - message: vec![0x00, 0x01, 0x02], + message: vec![0x00, 0x01, 0x02].try_into().unwrap(), gas_budget: 1_000, - cf_parameters: vec![], + cf_parameters: vec![].try_into().unwrap(), }, }; @@ -458,9 +458,9 @@ fn can_process_ccm_deposit() { let to_asset = Asset::Eth; let destination_address = ForeignChainAddress::Eth(Default::default()); let channel_metadata = CcmChannelMetadata { - message: vec![0x00, 0x01, 0x02], + message: vec![0x00, 0x01, 0x02].try_into().unwrap(), gas_budget: 1_000, - cf_parameters: vec![], + cf_parameters: vec![].try_into().unwrap(), }; let ccm = CcmDepositMetadata { source_chain: ForeignChain::Ethereum, @@ -527,9 +527,9 @@ fn can_egress_ccm() { source_chain: ForeignChain::Ethereum, source_address: Some(ForeignChainAddress::Eth([0xcf; 20].into())), channel_metadata: CcmChannelMetadata { - message: vec![0x00, 0x01, 0x02], + message: vec![0x00, 0x01, 0x02].try_into().unwrap(), gas_budget, - cf_parameters: vec![], + cf_parameters: vec![].try_into().unwrap(), } }; let amount = 5_000; @@ -548,7 +548,7 @@ fn can_egress_ccm() { amount, destination_address, message: ccm.channel_metadata.message.clone(), - cf_parameters: vec![], + cf_parameters: vec![].try_into().unwrap(), source_chain: ForeignChain::Ethereum, source_address: Some(ForeignChainAddress::Eth([0xcf; 20].into())), gas_budget, @@ -577,7 +577,7 @@ fn can_egress_ccm() { ccm.source_chain, ccm.source_address, gas_budget, - ccm.channel_metadata.message, + ccm.channel_metadata.message.to_vec(), ).unwrap()]); // Storage should be cleared diff --git a/state-chain/pallets/cf-swapping/src/benchmarking.rs b/state-chain/pallets/cf-swapping/src/benchmarking.rs index 0440e2cb7fc..3767eae039a 100644 --- a/state-chain/pallets/cf-swapping/src/benchmarking.rs +++ b/state-chain/pallets/cf-swapping/src/benchmarking.rs @@ -86,13 +86,13 @@ benchmarks! { call.dispatch_bypass_filter(gov_origin)?; let origin = T::EnsureWitnessed::try_successful_origin().unwrap(); - let metadata = CcmDepositMetadata { + let deposit_metadata = CcmDepositMetadata { source_chain: ForeignChain::Ethereum, source_address: Some(ForeignChainAddress::benchmark_value()), channel_metadata: CcmChannelMetadata { - message: vec![0x00], + message: vec![0x00].try_into().unwrap(), gas_budget: 1, - cf_parameters: vec![], + cf_parameters: Default::default(), } }; let call = Call::::ccm_deposit{ @@ -100,7 +100,7 @@ benchmarks! { deposit_amount: 1_000, destination_asset: Asset::Eth, destination_address: EncodedAddress::benchmark_value(), - deposit_metadata: metadata, + deposit_metadata, tx_hash: Default::default(), }; }: { diff --git a/state-chain/pallets/cf-swapping/src/lib.rs b/state-chain/pallets/cf-swapping/src/lib.rs index 5c95251c9e7..98857b5430a 100644 --- a/state-chain/pallets/cf-swapping/src/lib.rs +++ b/state-chain/pallets/cf-swapping/src/lib.rs @@ -117,7 +117,7 @@ enum BatchExecutionError { DispatchError { error: DispatchError }, } -/// This impl is never used. This is purely used to satisfy trait requirment +/// This impl is never used. This is purely used to satisfy trait requirement impl From for BatchExecutionError { fn from(error: DispatchError) -> Self { Self::DispatchError { error } diff --git a/state-chain/pallets/cf-swapping/src/tests.rs b/state-chain/pallets/cf-swapping/src/tests.rs index 2e9943a0191..8ddfe78c2b7 100644 --- a/state-chain/pallets/cf-swapping/src/tests.rs +++ b/state-chain/pallets/cf-swapping/src/tests.rs @@ -104,6 +104,21 @@ fn insert_swaps(swaps: &[Swap]) { } } +fn generate_ccm_channel() -> CcmChannelMetadata { + CcmChannelMetadata { + message: vec![0x01].try_into().unwrap(), + gas_budget: 1_000u128, + cf_parameters: Default::default(), + } +} +fn generate_ccm_deposit() -> CcmDepositMetadata { + CcmDepositMetadata { + source_chain: ForeignChain::Ethereum, + source_address: Some(ForeignChainAddress::Eth([0xcf; 20].into())), + channel_metadata: generate_ccm_channel(), + } +} + #[test] fn request_swap_success_with_valid_parameters() { new_test_ext().execute_with(|| { @@ -391,15 +406,7 @@ fn can_set_swap_ttl() { fn reject_invalid_ccm_deposit() { new_test_ext().execute_with(|| { let gas_budget = 1_000; - let ccm = CcmDepositMetadata { - source_chain: ForeignChain::Ethereum, - source_address: Some(ForeignChainAddress::Eth([0xcf; 20].into())), - channel_metadata: CcmChannelMetadata { - message: vec![0x00], - gas_budget, - cf_parameters: vec![], - }, - }; + let ccm = generate_ccm_deposit(); assert_noop!( Swapping::ccm_deposit( @@ -458,8 +465,7 @@ fn reject_invalid_ccm_deposit() { #[test] fn rejects_invalid_swap_deposit() { new_test_ext().execute_with(|| { - let gas_budget = 1_000; - let ccm = CcmChannelMetadata { message: vec![0x00], gas_budget, cf_parameters: vec![] }; + let ccm = generate_ccm_channel(); assert_noop!( Swapping::request_swap_deposit_address( @@ -533,13 +539,8 @@ fn can_process_ccms_via_swap_deposit_address() { new_test_ext().execute_with(|| { let gas_budget = 1_000; let deposit_amount = 10_000; - let request_ccm = - CcmChannelMetadata { message: vec![0x01], gas_budget, cf_parameters: vec![] }; - let ccm = CcmDepositMetadata { - source_chain: ForeignChain::Ethereum, - source_address: Some(ForeignChainAddress::Eth([0xcf; 20].into())), - channel_metadata: request_ccm.clone(), - }; + let request_ccm = generate_ccm_channel(); + let ccm = generate_ccm_deposit(); // Can process CCM via Swap deposit assert_ok!(Swapping::request_swap_deposit_address( @@ -598,8 +599,8 @@ fn can_process_ccms_via_swap_deposit_address() { asset: Asset::Eth, amount: deposit_amount - gas_budget, destination_address: ForeignChainAddress::Eth(Default::default()), - message: vec![0x01], - cf_parameters: vec![], + message: vec![0x01].try_into().unwrap(), + cf_parameters: vec![].try_into().unwrap(), gas_budget, },] ); @@ -621,17 +622,9 @@ fn can_process_ccms_via_swap_deposit_address() { #[test] fn can_process_ccms_via_extrinsic() { new_test_ext().execute_with(|| { - let gas_budget = 2_000; + let gas_budget = 1_000; let deposit_amount = 1_000_000; - let ccm = CcmDepositMetadata { - source_chain: ForeignChain::Ethereum, - source_address: Some(ForeignChainAddress::Eth([0xcf; 20].into())), - channel_metadata: CcmChannelMetadata { - message: vec![0x02], - gas_budget, - cf_parameters: vec![], - }, - }; + let ccm = generate_ccm_deposit(); // Can process CCM directly via Pallet Extrinsic. assert_ok!(Swapping::ccm_deposit( @@ -682,8 +675,8 @@ fn can_process_ccms_via_extrinsic() { asset: Asset::Usdc, amount: deposit_amount - gas_budget, destination_address: ForeignChainAddress::Eth(Default::default()), - message: vec![0x02], - cf_parameters: vec![], + message: vec![0x01].try_into().unwrap(), + cf_parameters: vec![].try_into().unwrap(), gas_budget, },] ); @@ -715,15 +708,7 @@ fn can_handle_ccms_with_non_native_gas_asset() { new_test_ext().execute_with(|| { let gas_budget = 1_000; let deposit_amount = 10_000; - let ccm = CcmDepositMetadata { - source_chain: ForeignChain::Ethereum, - source_address: Some(ForeignChainAddress::Eth([0xcf; 20].into())), - channel_metadata: CcmChannelMetadata { - message: vec![0x00], - gas_budget, - cf_parameters: vec![], - }, - }; + let ccm = generate_ccm_deposit(); assert_ok!(Swapping::ccm_deposit( RuntimeOrigin::root(), Asset::Eth, @@ -772,8 +757,8 @@ fn can_handle_ccms_with_non_native_gas_asset() { asset: Asset::Usdc, amount: deposit_amount - gas_budget, destination_address: ForeignChainAddress::Eth(Default::default()), - message: vec![0x00], - cf_parameters: vec![], + message: vec![0x01].try_into().unwrap(), + cf_parameters: vec![].try_into().unwrap(), gas_budget, },] ); @@ -805,15 +790,7 @@ fn can_handle_ccms_with_native_gas_asset() { new_test_ext().execute_with(|| { let gas_budget = 1_000; let deposit_amount = 10_000; - let ccm = CcmDepositMetadata { - source_chain: ForeignChain::Ethereum, - source_address: Some(ForeignChainAddress::Eth([0xcf; 20].into())), - channel_metadata: CcmChannelMetadata { - message: vec![0x00], - gas_budget, - cf_parameters: vec![], - }, - }; + let ccm = generate_ccm_deposit(); assert_ok!(Swapping::ccm_deposit( RuntimeOrigin::root(), @@ -857,8 +834,8 @@ fn can_handle_ccms_with_native_gas_asset() { asset: Asset::Usdc, amount: deposit_amount - gas_budget, destination_address: ForeignChainAddress::Eth(Default::default()), - message: vec![0x00], - cf_parameters: vec![], + message: vec![0x01].try_into().unwrap(), + cf_parameters: vec![].try_into().unwrap(), gas_budget, },] ); @@ -890,15 +867,7 @@ fn can_handle_ccms_with_no_swaps_needed() { new_test_ext().execute_with(|| { let gas_budget = 1_000; let deposit_amount = 10_000; - let ccm = CcmDepositMetadata { - source_chain: ForeignChain::Ethereum, - source_address: Some(ForeignChainAddress::Eth([0xcf; 20].into())), - channel_metadata: CcmChannelMetadata { - message: vec![0x00], - gas_budget, - cf_parameters: vec![], - }, - }; + let ccm = generate_ccm_deposit(); // Ccm without need for swapping are egressed directly. assert_ok!(Swapping::ccm_deposit( @@ -927,8 +896,8 @@ fn can_handle_ccms_with_no_swaps_needed() { asset: Asset::Eth, amount: deposit_amount - gas_budget, destination_address: ForeignChainAddress::Eth(Default::default()), - message: vec![0x00], - cf_parameters: vec![], + message: vec![0x01].try_into().unwrap(), + cf_parameters: vec![].try_into().unwrap(), gas_budget, },] ); @@ -1129,13 +1098,8 @@ fn ccm_via_deposit_with_principal_below_minimum_are_rejected() { let principal_amount = 2_000; let from: Asset = Asset::Eth; let to: Asset = Asset::Flip; - let request_ccm = - CcmChannelMetadata { message: vec![0x01], gas_budget, cf_parameters: vec![] }; - let ccm = CcmDepositMetadata { - source_chain: ForeignChain::Ethereum, - source_address: Some(ForeignChainAddress::Eth([0xcf; 20].into())), - channel_metadata: request_ccm.clone(), - }; + let request_ccm = generate_ccm_channel(); + let ccm = generate_ccm_deposit(); // Set minimum gas budget to be above gas amount assert_ok!(Swapping::set_minimum_swap_amount( @@ -1205,15 +1169,7 @@ fn ccm_via_extrinsic_with_principal_below_minimum_are_rejected() { let principal_amount = 2_000; let from: Asset = Asset::Eth; let to: Asset = Asset::Flip; - let ccm = CcmDepositMetadata { - source_chain: ForeignChain::Ethereum, - source_address: Some(ForeignChainAddress::Eth([0xcf; 20].into())), - channel_metadata: CcmChannelMetadata { - message: vec![0x01], - gas_budget, - cf_parameters: vec![], - }, - }; + let ccm = generate_ccm_deposit(); // Set minimum gas budget to be above gas amount assert_ok!(Swapping::set_minimum_swap_amount( @@ -1281,15 +1237,7 @@ fn ccm_without_principal_swaps_are_accepted() { let principal_amount = 10_000; let eth: Asset = Asset::Eth; let flip: Asset = Asset::Flip; - let ccm = CcmDepositMetadata { - source_chain: ForeignChain::Ethereum, - source_address: Some(ForeignChainAddress::Eth([0xcf; 20].into())), - channel_metadata: CcmChannelMetadata { - message: vec![0x01], - gas_budget, - cf_parameters: vec![], - }, - }; + let ccm = generate_ccm_deposit(); // Set minimum swap and gas budget. assert_ok!(Swapping::set_minimum_swap_amount( @@ -1372,15 +1320,7 @@ fn ccm_with_gas_below_minimum_swap_amount_allowed() { new_test_ext().execute_with(|| { let gas_budget = 1_000; let flip: Asset = Asset::Flip; - let ccm = CcmDepositMetadata { - source_chain: ForeignChain::Ethereum, - source_address: Some(ForeignChainAddress::Eth([0xcf; 20].into())), - channel_metadata: CcmChannelMetadata { - message: vec![0x01], - gas_budget, - cf_parameters: vec![], - }, - }; + let ccm = generate_ccm_deposit(); // Set minimum swap and gas budget. assert_ok!(Swapping::set_minimum_swap_amount(RuntimeOrigin::root(), flip, gas_budget + 1,)); @@ -1568,15 +1508,7 @@ fn cannot_withdraw_in_safe_mode() { #[test] fn ccm_swaps_emits_events() { new_test_ext().execute_with(|| { - let ccm = CcmDepositMetadata { - source_chain: ForeignChain::Ethereum, - source_address: Some(ForeignChainAddress::Eth([0xcf; 20].into())), - channel_metadata: CcmChannelMetadata { - message: vec![0x01], - gas_budget: 1_000, - cf_parameters: vec![], - }, - }; + let ccm = generate_ccm_deposit(); let destination_address = ForeignChainAddress::Eth(Default::default()); const ORIGIN: SwapOrigin = SwapOrigin::Vault { tx_hash: [0x11; 32] }; @@ -1691,19 +1623,11 @@ fn can_handle_ccm_with_zero_swap_outputs() { new_test_ext() .then_execute_at_next_block(|_| { let eth_address = ForeignChainAddress::Eth(Default::default()); - let ccm = CcmDepositMetadata { - source_chain: ForeignChain::Ethereum, - source_address: Some(eth_address.clone()), - channel_metadata: CcmChannelMetadata { - message: vec![], - gas_budget: 1, - cf_parameters: vec![], - }, - }; + let ccm = generate_ccm_deposit(); Swapping::on_ccm_deposit( Asset::Usdc, - 101, + 100_000, Asset::Eth, eth_address, ccm, @@ -1711,7 +1635,7 @@ fn can_handle_ccm_with_zero_swap_outputs() { ); // Change the swap rate so swap output will be 0 - SwapRate::set(0.01f64); + SwapRate::set(0.0001f64); System::reset_events(); }) .then_execute_with(|_| { @@ -1721,19 +1645,19 @@ fn can_handle_ccm_with_zero_swap_outputs() { RuntimeEvent::Swapping(Event::::SwapExecuted { swap_id: 1, source_asset: Asset::Usdc, - deposit_amount: 100, destination_asset: Asset::Eth, - egress_amount: 0, + deposit_amount: 99_000, + egress_amount: 9, intermediate_amount: None, }), RuntimeEvent::Swapping(Event::::SwapExecuted { swap_id: 2, source_asset: Asset::Usdc, + deposit_amount: 1_000, destination_asset: Asset::Eth, - deposit_amount: 1, egress_amount: 0, intermediate_amount: None, - }) + }), ); // CCM are processed and egressed even if principal output is zero. diff --git a/state-chain/runtime/src/lib.rs b/state-chain/runtime/src/lib.rs index faf5346b4e5..04ac0d1ccc6 100644 --- a/state-chain/runtime/src/lib.rs +++ b/state-chain/runtime/src/lib.rs @@ -41,7 +41,7 @@ pub use frame_support::{ instances::{Instance1, Instance2}, parameter_types, traits::{ - ConstBool, ConstU128, ConstU16, ConstU32, ConstU64, ConstU8, KeyOwnerProofSystem, + ConstBool, ConstU128, ConstU16, ConstU32, ConstU64, ConstU8, Get, KeyOwnerProofSystem, Randomness, StorageInfo, }, weights::{ diff --git a/state-chain/traits/src/mocks/egress_handler.rs b/state-chain/traits/src/mocks/egress_handler.rs index e215a01c60d..03f32ed2a09 100644 --- a/state-chain/traits/src/mocks/egress_handler.rs +++ b/state-chain/traits/src/mocks/egress_handler.rs @@ -1,6 +1,6 @@ use super::{MockPallet, MockPalletStorage}; use crate::EgressApi; -use cf_chains::{CcmDepositMetadata, Chain}; +use cf_chains::{CcmCfParameters, CcmDepositMetadata, CcmMessage, Chain}; use cf_primitives::{AssetAmount, EgressId, ForeignChain}; use codec::{Decode, Encode}; use scale_info::TypeInfo; @@ -23,8 +23,8 @@ pub enum MockEgressParameter { asset: C::ChainAsset, amount: C::ChainAmount, destination_address: C::ChainAccount, - message: Vec, - cf_parameters: Vec, + message: CcmMessage, + cf_parameters: CcmCfParameters, gas_budget: C::ChainAmount, }, }