Skip to content

Commit

Permalink
feat: dca parameters in channel actions + migration
Browse files Browse the repository at this point in the history
  • Loading branch information
msgmaxim committed Aug 2, 2024
1 parent 7a66f1f commit 30e1915
Show file tree
Hide file tree
Showing 8 changed files with 253 additions and 12 deletions.
10 changes: 6 additions & 4 deletions state-chain/pallets/cf-ingress-egress/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ impl<C: Chain> CrossChainMessage<C> {
}
}

pub const PALLET_VERSION: StorageVersion = StorageVersion::new(11);
pub const PALLET_VERSION: StorageVersion = StorageVersion::new(12);

impl_pallet_safe_mode! {
PalletSafeMode<I>;
Expand Down Expand Up @@ -304,7 +304,7 @@ pub mod pallet {
destination_address: ForeignChainAddress,
channel_metadata: CcmChannelMetadata,
refund_params: Option<ChannelRefundParameters>,
// TODO: add DCA params
dca_params: Option<DCAParameters>,
},
}

Expand Down Expand Up @@ -1564,6 +1564,7 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
destination_address,
channel_metadata,
refund_params,
dca_params: _,
} => {
if let Ok(swap_request_id) = T::SwapRequestHandler::init_swap_request(
asset.into(),
Expand Down Expand Up @@ -2032,9 +2033,9 @@ impl<T: Config<I>, I: 'static> DepositApi<T::TargetChain> for Pallet<T, I> {
(ChannelId, ForeignChainAddress, <T::TargetChain as Chain>::ChainBlockNumber, Self::Amount),
DispatchError,
> {
if let Some(refund_params) = &refund_params {
if let Some(params) = &refund_params {
ensure!(
refund_params.retry_duration <= MaxSwapRetryDurationBlocks::<T, I>::get(),
params.retry_duration <= MaxSwapRetryDurationBlocks::<T, I>::get(),
DispatchError::Other("Retry duration too long")
);
}
Expand All @@ -2048,6 +2049,7 @@ impl<T: Config<I>, I: 'static> DepositApi<T::TargetChain> for Pallet<T, I> {
destination_address,
channel_metadata,
refund_params,
dca_params,
},
None => ChannelAction::Swap {
destination_asset,
Expand Down
5 changes: 4 additions & 1 deletion state-chain/pallets/cf-ingress-egress/src/migrations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ mod add_refund_params;
pub mod remove_prewitnessed_deposits;
pub mod withheld_transaction_fees;

mod add_dca_params;

pub type PalletMigration<T, I> = (
VersionedMigration<Pallet<T, I>, remove_prewitnessed_deposits::Migration<T, I>, 8, 9>,
VersionedMigration<Pallet<T, I>, add_refund_params::Migration<T, I>, 9, 10>,
VersionedMigration<Pallet<T, I>, withheld_transaction_fees::Migration<T, I>, 10, 11>,
PlaceholderMigration<Pallet<T, I>, 11>,
VersionedMigration<Pallet<T, I>, add_dca_params::Migration<T, I>, 11, 12>,
PlaceholderMigration<Pallet<T, I>, 12>,
);
233 changes: 233 additions & 0 deletions state-chain/pallets/cf-ingress-egress/src/migrations/add_dca_params.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
use crate::*;
use frame_support::traits::OnRuntimeUpgrade;

pub(super) mod old {

use super::*;

#[derive(Clone, RuntimeDebug, PartialEq, Eq, Encode, Decode, TypeInfo)]
pub enum ChannelAction<AccountId> {
Swap {
destination_asset: Asset,
destination_address: ForeignChainAddress,
broker_fees: Beneficiaries<AccountId>,
refund_params: Option<ChannelRefundParameters>,
},
LiquidityProvision {
lp_account: AccountId,
},
CcmTransfer {
destination_asset: Asset,
destination_address: ForeignChainAddress,
channel_metadata: CcmChannelMetadata,
refund_params: Option<ChannelRefundParameters>,
},
}

#[derive(CloneNoBound, RuntimeDebug, PartialEq, Eq, Encode, Decode, TypeInfo)]
#[scale_info(skip_type_params(T, I))]
pub struct DepositChannelDetails<T: Config<I>, I: 'static> {
pub deposit_channel: DepositChannel<T::TargetChain>,
/// The block number at which the deposit channel was opened, expressed as a block number
/// on the external Chain.
pub opened_at: TargetChainBlockNumber<T, I>,
/// The last block on the target chain that the witnessing will witness it in. If funds are
/// sent after this block, they will not be witnessed.
pub expires_at: TargetChainBlockNumber<T, I>,

/// The action to be taken when the DepositChannel is deposited to.
pub action: ChannelAction<T::AccountId>,
/// The boost fee
pub boost_fee: BasisPoints,
/// Boost status, indicating whether there is pending boost on the channel
pub boost_status: BoostStatus<TargetChainAmount<T, I>>,
}

#[frame_support::storage_alias]
pub type DepositChannelLookup<T: Config<I>, I: 'static> = StorageMap<
Pallet<T, I>,
Twox64Concat,
TargetChainAccount<T, I>,
DepositChannelDetails<T, I>,
OptionQuery,
>;
}

pub struct Migration<T: Config<I>, I: 'static>(PhantomData<(T, I)>);

impl<T: Config<I>, I: 'static> OnRuntimeUpgrade for Migration<T, I> {
fn on_runtime_upgrade() -> Weight {
DepositChannelLookup::<T, I>::translate(|_, details: old::DepositChannelDetails<T, I>| {
Some(DepositChannelDetails {
deposit_channel: details.deposit_channel,
opened_at: details.opened_at,
expires_at: details.expires_at,
action: match details.action {
old::ChannelAction::Swap {
destination_asset,
destination_address,
broker_fees,
refund_params,
} => ChannelAction::Swap {
destination_asset,
destination_address,
broker_fees,
refund_params,
dca_params: None,
},
old::ChannelAction::LiquidityProvision { lp_account } =>
ChannelAction::LiquidityProvision { lp_account },
old::ChannelAction::CcmTransfer {
destination_asset,
destination_address,
channel_metadata,
refund_params,
} => ChannelAction::CcmTransfer {
destination_asset,
destination_address,
channel_metadata,
refund_params,
dca_params: None,
},
},
boost_fee: details.boost_fee,
boost_status: details.boost_status,
})
});

Weight::zero()
}

#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<Vec<u8>, DispatchError> {
Ok(vec![])
}

#[cfg(feature = "try-runtime")]
fn post_upgrade(_state: Vec<u8>) -> Result<(), DispatchError> {
Ok(())
}
}

#[cfg(test)]
mod tests {

use super::*;

use crate::mock_btc::{new_test_ext, Test};
use cf_chains::{
btc::{
deposit_address::{DepositAddress, TapscriptPath},
BitcoinScript, ScriptPubkey,
},
Bitcoin,
};

fn mock_deposit_channel() -> DepositChannel<Bitcoin> {
DepositChannel {
channel_id: 123,
address: ScriptPubkey::Taproot([0u8; 32]).clone(),
asset: <Bitcoin as Chain>::ChainAsset::Btc,
state: DepositAddress {
pubkey_x: [1u8; 32],
script_path: Some(TapscriptPath {
salt: 123,
tweaked_pubkey_bytes: [2u8; 33],
tapleaf_hash: [3u8; 32],
unlock_script: BitcoinScript::new(Default::default()),
}),
},
}
}

#[test]
fn test_migration() {
new_test_ext().execute_with(|| {
let input_address_1 = ScriptPubkey::Taproot([0u8; 32]);
let input_address_2 = ScriptPubkey::Taproot([1u8; 32]);
let output_address = ForeignChainAddress::Eth([0u8; 20].into());

let refund_params = ChannelRefundParameters {
retry_duration: 40,
refund_address: ForeignChainAddress::Eth([3u8; 20].into()),
min_price: 2.into(),
};

let old_details_swap = old::DepositChannelDetails::<Test, _> {
deposit_channel: mock_deposit_channel(),
opened_at: Default::default(),
expires_at: Default::default(),
boost_status: BoostStatus::NotBoosted,
action: old::ChannelAction::Swap {
destination_asset: Asset::Flip,
destination_address: output_address.clone(),
broker_fees: Default::default(),
refund_params: Some(refund_params.clone()),
},
boost_fee: 0,
};

let old_details_ccm = old::DepositChannelDetails::<Test, _> {
action: old::ChannelAction::CcmTransfer {
destination_asset: Asset::Flip,
destination_address: output_address.clone(),
channel_metadata: CcmChannelMetadata {
message: vec![0u8, 1u8, 2u8, 3u8, 4u8].try_into().unwrap(),
gas_budget: 50 * 10u128.pow(18),
cf_parameters: Default::default(),
},
refund_params: Some(refund_params.clone()),
},
..old_details_swap.clone()
};

old::DepositChannelLookup::<Test, ()>::insert(
input_address_1.clone(),
old_details_swap,
);

old::DepositChannelLookup::<Test, ()>::insert(input_address_2.clone(), old_details_ccm);

Migration::<Test, ()>::on_runtime_upgrade();

assert_eq!(
DepositChannelLookup::<Test, ()>::get(input_address_1),
Some(DepositChannelDetails::<Test, _> {
deposit_channel: mock_deposit_channel(),
opened_at: Default::default(),
expires_at: Default::default(),
boost_status: BoostStatus::NotBoosted,
action: ChannelAction::Swap {
destination_asset: Asset::Flip,
destination_address: output_address.clone(),
broker_fees: Default::default(),
refund_params: Some(refund_params.clone()),
dca_params: None,
},
boost_fee: 0,
})
);
assert_eq!(
DepositChannelLookup::<Test, ()>::get(input_address_2),
Some(DepositChannelDetails::<Test, _> {
deposit_channel: mock_deposit_channel(),
opened_at: Default::default(),
expires_at: Default::default(),
boost_status: BoostStatus::NotBoosted,
action: ChannelAction::CcmTransfer {
destination_asset: Asset::Flip,
destination_address: output_address.clone(),
channel_metadata: CcmChannelMetadata {
message: vec![0u8, 1u8, 2u8, 3u8, 4u8].try_into().unwrap(),
gas_budget: 50 * 10u128.pow(18),
cf_parameters: Default::default(),
},
refund_params: Some(refund_params.clone()),
dca_params: None,
},
boost_fee: 0,
})
);
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ impl<T: Config<I>, I: 'static> OnRuntimeUpgrade for Migration<T, I> {
destination_address,
channel_metadata,
refund_params: None,
dca_params: None,
},
},
boost_fee: details.boost_fee,
Expand Down Expand Up @@ -210,6 +211,7 @@ mod tests {
cf_parameters: Default::default(),
},
refund_params: None,
dca_params: None,
},
boost_fee: 0,
})
Expand Down
1 change: 1 addition & 0 deletions state-chain/pallets/cf-swapping/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ mod benchmarks {
channel_metadata: None,
refund_parameters: None,
affiliate_fees,
dca_parameters: None,
};

#[block]
Expand Down
2 changes: 1 addition & 1 deletion state-chain/pallets/cf-swapping/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1905,7 +1905,7 @@ fn deposit_address_ready_event_contains_correct_parameters() {
min_price: 100.into(),
};

let dca_parameters = DCAParameters { number_of_chunks: 5, swap_interval: 2 };
let dca_parameters = DCAParameters { number_of_chunks: 5, chunk_interval: 2 };

const BOOST_FEE: u16 = 100;
assert_ok!(Swapping::request_swap_deposit_address_with_affiliates(
Expand Down
10 changes: 5 additions & 5 deletions state-chain/pallets/cf-swapping/src/tests/dca.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ fn dca_happy_path() {
assert_eq!(System::block_number(), INITIAL_BLOCK);

insert_swaps(&[params(
Some(DCAParameters { number_of_chunks: 2, swap_interval: SWAP_INTERVAL }),
Some(DCAParameters { number_of_chunks: 2, chunk_interval: SWAP_INTERVAL }),
None,
)]);

Expand Down Expand Up @@ -120,7 +120,7 @@ fn dca_single_chunk() {
assert_eq!(System::block_number(), INITIAL_BLOCK);

insert_swaps(&[params(
Some(DCAParameters { number_of_chunks: 1, swap_interval: SWAP_INTERVAL }),
Some(DCAParameters { number_of_chunks: 1, chunk_interval: SWAP_INTERVAL }),
None,
)]);

Expand Down Expand Up @@ -185,7 +185,7 @@ fn dca_with_fok_full_refund() {
insert_swaps(&[params(
Some(DCAParameters {
number_of_chunks: NUMBER_OF_CHUNKS,
swap_interval: SWAP_INTERVAL,
chunk_interval: SWAP_INTERVAL,
}),
Some(SwapRefundParameters {
refund_block: REFUND_BLOCK as u32,
Expand Down Expand Up @@ -265,7 +265,7 @@ fn dca_with_fok_partial_refund() {
insert_swaps(&[params(
Some(DCAParameters {
number_of_chunks: NUMBER_OF_CHUNKS,
swap_interval: SWAP_INTERVAL,
chunk_interval: SWAP_INTERVAL,
}),
Some(SwapRefundParameters {
refund_block: REFUND_BLOCK as u32,
Expand Down Expand Up @@ -363,7 +363,7 @@ fn dca_with_fok_fully_executed() {
insert_swaps(&[params(
Some(DCAParameters {
number_of_chunks: NUMBER_OF_CHUNKS,
swap_interval: SWAP_INTERVAL,
chunk_interval: SWAP_INTERVAL,
}),
Some(SwapRefundParameters {
refund_block: CHUNK_2_BLOCK as u32,
Expand Down
2 changes: 1 addition & 1 deletion state-chain/primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,5 +349,5 @@ pub struct DCAParameters {
/// The number of individual swaps to be executed
pub number_of_chunks: u32,
/// The interval in blocks between each swap.
pub swap_interval: u32,
pub chunk_interval: u32,
}

0 comments on commit 30e1915

Please sign in to comment.