Skip to content

Commit

Permalink
feat: add boost fee field to DepositChannelDetails (#4492)
Browse files Browse the repository at this point in the history
  • Loading branch information
marcellorigotti authored Feb 8, 2024
1 parent a9b89ed commit a872e5d
Show file tree
Hide file tree
Showing 15 changed files with 235 additions and 9 deletions.
1 change: 1 addition & 0 deletions engine/src/witness/btc/btc_deposits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ pub mod tests {
action: ChannelAction::<AccountId32>::LiquidityProvision {
lp_account: AccountId32::new([0xab; 32]),
},
boost_fee: 0,
}
}

Expand Down
2 changes: 2 additions & 0 deletions state-chain/pallets/cf-ingress-egress/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ mod benchmarks {
action: ChannelAction::<T::AccountId>::LiquidityProvision {
lp_account: account("doogle", 0, 0),
},
boost_fee: 0,
},
);

Expand Down Expand Up @@ -108,6 +109,7 @@ mod benchmarks {
action: ChannelAction::<T::AccountId>::LiquidityProvision {
lp_account: account("doogle", 0, 0),
},
boost_fee: 0,
};
channel.deposit_channel.state.on_fetch_scheduled();
DepositChannelLookup::<T, I>::insert(deposit_address.clone(), channel);
Expand Down
16 changes: 13 additions & 3 deletions state-chain/pallets/cf-ingress-egress/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ impl<C: Chain> CrossChainMessage<C> {
}
}

pub const PALLET_VERSION: StorageVersion = StorageVersion::new(4);
pub const PALLET_VERSION: StorageVersion = StorageVersion::new(5);

/// Calls to the external chains that has failed to be broadcast/accepted by the target chain.
/// User can use information stored here to query for relevant information to broadcast
Expand Down Expand Up @@ -161,6 +161,8 @@ pub mod pallet {

/// The action to be taken when the DepositChannel is deposited to.
pub action: ChannelAction<T::AccountId>,
/// The boost fee
pub boost_fee: BasisPoints,
}

pub enum IngressOrEgress {
Expand Down Expand Up @@ -1142,6 +1144,7 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
fn open_channel(
source_asset: TargetChainAsset<T, I>,
action: ChannelAction<T::AccountId>,
boost_fee: BasisPoints,
) -> Result<(ChannelId, TargetChainAccount<T, I>, TargetChainBlockNumber<T, I>), DispatchError>
{
let (deposit_channel, channel_id) = if let Some((channel_id, mut deposit_channel)) =
Expand Down Expand Up @@ -1183,6 +1186,7 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
opened_at: current_height,
expires_at: expiry_height,
action,
boost_fee,
},
);

Expand Down Expand Up @@ -1330,12 +1334,16 @@ impl<T: Config<I>, I: 'static> DepositApi<T::TargetChain> for Pallet<T, I> {
fn request_liquidity_deposit_address(
lp_account: T::AccountId,
source_asset: TargetChainAsset<T, I>,
boost_fee: BasisPoints,
) -> Result<
(ChannelId, ForeignChainAddress, <T::TargetChain as Chain>::ChainBlockNumber),
DispatchError,
> {
let (channel_id, deposit_address, expiry_block) =
Self::open_channel(source_asset, ChannelAction::LiquidityProvision { lp_account })?;
let (channel_id, deposit_address, expiry_block) = Self::open_channel(
source_asset,
ChannelAction::LiquidityProvision { lp_account },
boost_fee,
)?;

Ok((channel_id, deposit_address.into(), expiry_block))
}
Expand All @@ -1348,6 +1356,7 @@ impl<T: Config<I>, I: 'static> DepositApi<T::TargetChain> for Pallet<T, I> {
broker_commission_bps: BasisPoints,
broker_id: T::AccountId,
channel_metadata: Option<CcmChannelMetadata>,
boost_fee: BasisPoints,
) -> Result<
(ChannelId, ForeignChainAddress, <T::TargetChain as Chain>::ChainBlockNumber),
DispatchError,
Expand All @@ -1367,6 +1376,7 @@ impl<T: Config<I>, I: 'static> DepositApi<T::TargetChain> for Pallet<T, I> {
broker_id,
},
},
boost_fee,
)?;

Ok((channel_id, deposit_address.into(), expiry_height))
Expand Down
2 changes: 2 additions & 0 deletions state-chain/pallets/cf-ingress-egress/src/migrations.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
pub mod btc_deposit_channels;
pub mod deposit_channels_with_boost_fee;
pub mod set_dust_limit;

use cf_runtime_upgrade_utilities::VersionedMigration;

pub type PalletMigration<T, I> = (
VersionedMigration<crate::Pallet<T, I>, btc_deposit_channels::Migration<T, I>, 2, 3>,
VersionedMigration<crate::Pallet<T, I>, set_dust_limit::Migration<T, I>, 3, 4>,
VersionedMigration<crate::Pallet<T, I>, deposit_channels_with_boost_fee::Migration<T, I>, 4, 5>,
);
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ impl<T: Config<Instance3, TargetChain = Bitcoin>> OnRuntimeUpgrade for Migration
opened_at: old_channel.opened_at,
expires_at: old_channel.expires_at,
action: old_channel.action,
boost_fee: 0,
})
},
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
use crate::*;
use cf_chains::DepositChannel;
use frame_support::traits::OnRuntimeUpgrade;
pub struct Migration<T: Config<I>, I: 'static>(PhantomData<(T, I)>);

mod old {
use super::*;

#[derive(
CloneNoBound, RuntimeDebug, PartialEq, Eq, Encode, Decode, TypeInfo, MaxEncodedLen,
)]
#[scale_info(skip_type_params(T, I))]
pub struct DepositChannelDetails<T: Config<I>, I: 'static> {
pub deposit_channel: DepositChannel<T::TargetChain>,
pub opened_at: TargetChainBlockNumber<T, I>,
pub expires_at: TargetChainBlockNumber<T, I>,
pub action: ChannelAction<T::AccountId>,
}

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

impl<T: Config<I>, I: 'static> OnRuntimeUpgrade for Migration<T, I> {
fn on_runtime_upgrade() -> Weight {
DepositChannelLookup::<T, I>::translate(
|_address, old_channel: old::DepositChannelDetails<T, I>| {
Some(DepositChannelDetails::<T, I> {
deposit_channel: old_channel.deposit_channel,
opened_at: old_channel.opened_at,
expires_at: old_channel.expires_at,
action: old_channel.action,
boost_fee: 0,
})
},
);
Weight::zero()
}

#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<Vec<u8>, DispatchError> {
let number_of_channels_in_lookup =
old::DepositChannelLookup::<T, I>::iter_keys().count() as u32;

Ok(number_of_channels_in_lookup.encode())
}

#[cfg(feature = "try-runtime")]
fn post_upgrade(state: Vec<u8>) -> Result<(), DispatchError> {
let number_of_channels_in_lookup_pre_migration = <u32>::decode(&mut &state[..]).unwrap();
ensure!(
DepositChannelLookup::<T, I>::iter_keys().count() as u32 ==
number_of_channels_in_lookup_pre_migration,
"DepositChannelLookup migration failed."
);
Ok(())
}
}

#[cfg(test)]
mod migration_tests {
use cf_chains::btc::{
deposit_address::{DepositAddress, TapscriptPath},
BitcoinScript, ScriptPubkey,
};

use self::mock_btc::new_test_ext;

use super::*;
use crate::mock_btc::*;

#[test]
fn test_migration() {
new_test_ext().execute_with(|| {
let address1 = ScriptPubkey::Taproot([0u8; 32]);
let address2 = ScriptPubkey::Taproot([1u8; 32]);

// Insert mock data into old storage
old::DepositChannelLookup::insert(address1.clone(), mock_deposit_channel_details());
old::DepositChannelLookup::insert(address2.clone(), mock_deposit_channel_details());
#[cfg(feature = "try-runtime")]
let state: Vec<u8> = crate::migrations::deposit_channels_with_boost_fee::Migration::<Test, _>::pre_upgrade().unwrap();

// Perform runtime migration.
crate::migrations::deposit_channels_with_boost_fee::Migration::<Test, _>::on_runtime_upgrade();

#[cfg(feature = "try-runtime")]
crate::migrations::deposit_channels_with_boost_fee::Migration::<Test, _>::post_upgrade(state).unwrap();

// Verify data is correctly migrated into new storage.
let channel = DepositChannelLookup::<Test, Instance3>::get(address1);
assert!(channel.is_some());
assert_eq!(channel.unwrap().boost_fee, 0);
let channel = DepositChannelLookup::<Test, Instance3>::get(address2);
assert!(channel.is_some());
assert_eq!(channel.unwrap().boost_fee, 0);
});
}

fn mock_deposit_channel_details() -> old::DepositChannelDetails<Test, Instance3> {
old::DepositChannelDetails::<Test, _> {
deposit_channel: 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()),
}),
},
},
opened_at: Default::default(),
expires_at: Default::default(),
action: ChannelAction::LiquidityProvision { lp_account: Default::default() },
}
}
}
3 changes: 2 additions & 1 deletion state-chain/pallets/cf-ingress-egress/src/mock_eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ impl<Ctx: Clone> RequestAddress for TestExternalities<Test, Ctx> {
.cloned()
.map(|request| match request {
DepositRequest::Liquidity { lp_account, asset } =>
IngressEgress::request_liquidity_deposit_address(lp_account, asset)
IngressEgress::request_liquidity_deposit_address(lp_account, asset, 0)
.map(|(id, addr, ..)| {
(request, id, TestChainAccount::try_from(addr).unwrap())
})
Expand All @@ -246,6 +246,7 @@ impl<Ctx: Clone> RequestAddress for TestExternalities<Test, Ctx> {
Default::default(),
BROKER,
None,
0,
)
.map(|(channel_id, deposit_address, ..)| {
(request, channel_id, TestChainAccount::try_from(deposit_address).unwrap())
Expand Down
11 changes: 7 additions & 4 deletions state-chain/pallets/cf-ingress-egress/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,8 @@ fn request_address_and_deposit(
who: ChannelId,
asset: eth::Asset,
) -> (ChannelId, <Ethereum as Chain>::ChainAccount) {
let (id, address, ..) = IngressEgress::request_liquidity_deposit_address(who, asset).unwrap();
let (id, address, ..) =
IngressEgress::request_liquidity_deposit_address(who, asset, 0).unwrap();
let address: <Ethereum as Chain>::ChainAccount = address.try_into().unwrap();
assert_ok!(IngressEgress::process_single_deposit(
address,
Expand Down Expand Up @@ -439,6 +440,7 @@ fn reused_address_channel_id_matches() {
let (reused_channel_id, reused_address, ..) = IngressEgress::open_channel(
eth::Asset::Eth,
ChannelAction::LiquidityProvision { lp_account: 0 },
0,
)
.unwrap();
// The reused details should be the same as before.
Expand Down Expand Up @@ -474,6 +476,7 @@ fn can_process_ccm_deposit() {
0,
1,
Some(channel_metadata),
0,
)
.unwrap();

Expand Down Expand Up @@ -578,7 +581,7 @@ fn multi_deposit_includes_deposit_beyond_recycle_height() {
new_test_ext()
.then_execute_at_next_block(|_| {
let (_, address, ..) =
IngressEgress::request_liquidity_deposit_address(ALICE, ETH).unwrap();
IngressEgress::request_liquidity_deposit_address(ALICE, ETH, 0).unwrap();
let address: <Ethereum as Chain>::ChainAccount = address.try_into().unwrap();
let recycles_at = IngressEgress::expiry_and_recycle_block_height().2;
(address, recycles_at)
Expand All @@ -589,7 +592,7 @@ fn multi_deposit_includes_deposit_beyond_recycle_height() {
})
.then_execute_at_next_block(|address| {
let (_, address2, ..) =
IngressEgress::request_liquidity_deposit_address(ALICE, ETH).unwrap();
IngressEgress::request_liquidity_deposit_address(ALICE, ETH, 0).unwrap();
let address2: <Ethereum as Chain>::ChainAccount = address2.try_into().unwrap();
(address, address2)
})
Expand Down Expand Up @@ -906,7 +909,7 @@ fn deposits_ingress_fee_exceeding_deposit_amount_rejected() {
});

let (_id, address, ..) =
IngressEgress::request_liquidity_deposit_address(ALICE, ASSET).unwrap();
IngressEgress::request_liquidity_deposit_address(ALICE, ASSET, 0).unwrap();
let deposit_address = address.try_into().unwrap();

// Swap a low enough amount such that it gets swallowed by fees
Expand Down
6 changes: 5 additions & 1 deletion state-chain/pallets/cf-lp/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,11 @@ pub mod pallet {
);

let (channel_id, deposit_address, expiry_block) =
T::DepositHandler::request_liquidity_deposit_address(account_id.clone(), asset)?;
T::DepositHandler::request_liquidity_deposit_address(
account_id.clone(),
asset,
boost_fee,
)?;

Self::deposit_event(Event::LiquidityDepositAddressReady {
channel_id,
Expand Down
42 changes: 42 additions & 0 deletions state-chain/pallets/cf-lp/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,3 +215,45 @@ fn cannot_request_deposit_address_without_registering_liquidity_refund_address()
), crate::Error::<Test>::NoLiquidityRefundAddressRegistered);
});
}

#[test]
fn deposit_address_ready_event_contain_correct_boost_fee_value() {
new_test_ext().execute_with(|| {
const BOOST_FEE1: u16 = 0;
const BOOST_FEE2: u16 = 50;
const BOOST_FEE3: u16 = 100;

assert_ok!(LiquidityProvider::register_liquidity_refund_address(
RuntimeOrigin::signed(LP_ACCOUNT.into()),
EncodedAddress::Eth([0x01; 20])
));

assert_ok!(LiquidityProvider::request_liquidity_deposit_address(
RuntimeOrigin::signed(LP_ACCOUNT.into()),
Asset::Eth,
BOOST_FEE1,
));
assert_ok!(LiquidityProvider::request_liquidity_deposit_address(
RuntimeOrigin::signed(LP_ACCOUNT.into()),
Asset::Flip,
BOOST_FEE2,
));
assert_ok!(LiquidityProvider::request_liquidity_deposit_address(
RuntimeOrigin::signed(LP_ACCOUNT.into()),
Asset::Usdc,
BOOST_FEE3,
));
assert_events_match!(Test, RuntimeEvent::LiquidityProvider(crate::Event::LiquidityDepositAddressReady {
boost_fee: BOOST_FEE1,
..
}) => (),
RuntimeEvent::LiquidityProvider(crate::Event::LiquidityDepositAddressReady {
boost_fee: BOOST_FEE2,
..
}) => (),
RuntimeEvent::LiquidityProvider(crate::Event::LiquidityDepositAddressReady {
boost_fee: BOOST_FEE3,
..
}) => ());
});
}
1 change: 1 addition & 0 deletions state-chain/pallets/cf-swapping/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,7 @@ pub mod pallet {
broker_commission_bps,
broker,
channel_metadata.clone(),
boost_fee,
)?;

Self::deposit_event(Event::<T>::SwapDepositAddressReady {
Expand Down
Loading

0 comments on commit a872e5d

Please sign in to comment.