Skip to content

Commit

Permalink
Make issuer decide migration type
Browse files Browse the repository at this point in the history
  • Loading branch information
JuaniRios committed Jun 25, 2024
1 parent b122521 commit ee1f336
Show file tree
Hide file tree
Showing 10 changed files with 422 additions and 349 deletions.
15 changes: 11 additions & 4 deletions integration-tests/src/tests/ct_migration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

use crate::*;
use frame_support::traits::{fungible::Mutate, fungibles::Inspect};
use pallet_funding::{assert_close_enough, ProjectId};
use pallet_funding::{assert_close_enough, types::*, ProjectId};
use polimec_common::migration_types::{MigrationStatus, Migrations};
use polimec_runtime::Funding;
use sp_runtime::Perquintill;
Expand All @@ -34,7 +34,7 @@ fn mock_hrmp_establishment(project_id: u32) {
});

PolimecNet::execute_with(|| {
assert_ok!(Funding::do_set_para_id_for_project(&ISSUER.into(), project_id, ParaId::from(6969u32)));
assert_ok!(Funding::do_configure_receiver_pallet_migration(&ISSUER.into(), project_id, ParaId::from(6969u32)));

let open_channel_message = xcm::v3::opaque::Instruction::HrmpNewChannelOpenRequest {
sender: 6969,
Expand All @@ -54,7 +54,10 @@ fn mock_hrmp_establishment(project_id: u32) {
fn assert_migration_is_ready(project_id: u32) {
PolimecNet::execute_with(|| {
let project_details = pallet_funding::ProjectsDetails::<PolimecRuntime>::get(project_id).unwrap();
assert!(project_details.migration_readiness_check.unwrap().is_ready())
let MigrationType::ParachainReceiverPallet(receiver_pallet_info) = project_details.migration_type else {
panic!("Migration type is not ParachainReceiverPallet");
};
assert!(receiver_pallet_info.migration_readiness_check.unwrap().is_ready())
});
}

Expand All @@ -76,7 +79,11 @@ fn get_migrations_for_participants(
fn send_migrations(project_id: ProjectId, accounts: Vec<AccountId>) {
for user in accounts.into_iter() {
PolimecNet::execute_with(|| {
assert_ok!(Funding::migrate_one_participant(PolimecOrigin::signed(user.clone()), project_id, user.clone()));
assert_ok!(Funding::receiver_pallet_migrate_for(
PolimecOrigin::signed(user.clone()),
project_id,
user.clone()
));
});
}
}
Expand Down
13 changes: 10 additions & 3 deletions integration-tests/src/tests/e2e.rs
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,11 @@ fn ct_migrated() {
// Mock HRMP establishment
PolimecNet::execute_with(|| {
let _account_id: PolimecAccountId = ISSUER.into();
assert_ok!(PolimecFunding::do_set_para_id_for_project(&ISSUER.into(), project_id, ParaId::from(6969u32),));
assert_ok!(PolimecFunding::do_configure_receiver_pallet_migration(
&ISSUER.into(),
project_id,
ParaId::from(6969u32),
));
let open_channel_message = xcm::v3::opaque::Instruction::HrmpNewChannelOpenRequest {
sender: 6969,
max_message_size: 102_300,
Expand All @@ -505,7 +509,10 @@ fn ct_migrated() {
// Migration is ready
PolimecNet::execute_with(|| {
let project_details = pallet_funding::ProjectsDetails::<PolimecRuntime>::get(project_id).unwrap();
assert!(project_details.migration_readiness_check.unwrap().is_ready())
let MigrationType::ParachainReceiverPallet(migration_info) = project_details.migration_type else {
panic!("Migration type should be ParachainReceiverPallet");
};
assert!(migration_info.migration_readiness_check.unwrap().is_ready())
});

excel_ct_amounts().iter().map(|tup| tup.0.clone()).unique().for_each(|account| {
Expand All @@ -525,7 +532,7 @@ fn ct_migrated() {

for account in accounts {
PolimecNet::execute_with(|| {
assert_ok!(PolimecFunding::migrate_one_participant(
assert_ok!(PolimecFunding::receiver_pallet_migrate_for(
PolimecOrigin::signed(account.clone()),
project_id,
account.clone()
Expand Down
7 changes: 1 addition & 6 deletions pallets/funding/src/functions/1_application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,7 @@ impl<T: Config> Pallet<T> {
},
usd_bid_on_oversubscription: None,
funding_end_block: None,
parachain_id: None,
migration_readiness_check: None,
hrmp_channel_status: HRMPChannelStatus {
project_to_polimec: ChannelStatus::Closed,
polimec_to_project: ChannelStatus::Closed,
},
migration_type: MigrationType::Offchain,
};

let bucket: BucketOf<T> = Self::create_bucket_from_metadata(&project_metadata)?;
Expand Down
102 changes: 71 additions & 31 deletions pallets/funding/src/functions/7_ct_migration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use xcm::v3::MaxPalletNameLen;

impl<T: Config> Pallet<T> {
#[transactional]
pub fn do_set_para_id_for_project(
pub fn do_configure_receiver_pallet_migration(
caller: &AccountIdOf<T>,
project_id: ProjectId,
para_id: ParaId,
Expand All @@ -13,9 +13,18 @@ impl<T: Config> Pallet<T> {

// * Validity checks *
ensure!(&(project_details.issuer_account) == caller, Error::<T>::NotIssuer);
ensure!(project_details.status == ProjectStatus::FundingSuccessful, Error::<T>::IncorrectRound);

// * Update storage *
project_details.parachain_id = Some(para_id);
let parachain_receiver_pallet_info = ParachainReceiverPalletInfo {
parachain_id: para_id,
hrmp_channel_status: HRMPChannelStatus {
project_to_polimec: ChannelStatus::Closed,
polimec_to_project: ChannelStatus::Closed,
},
migration_readiness_check: None,
};
project_details.migration_type = MigrationType::ParachainReceiverPallet(parachain_receiver_pallet_info);
ProjectsDetails::<T>::insert(project_id, project_details);

// * Emit events *
Expand Down Expand Up @@ -51,7 +60,10 @@ impl<T: Config> Pallet<T> {

let (project_id, mut project_details) = ProjectsDetails::<T>::iter()
.find(|(_id, details)| {
details.parachain_id == Some(ParaId::from(sender)) && details.status == FundingSuccessful
matches!(
&details.migration_type,
MigrationType::ParachainReceiverPallet(info) if
info.parachain_id == ParaId::from(sender) && details.status == FundingSuccessful)
})
.ok_or(XcmError::BadOrigin)?;

Expand Down Expand Up @@ -95,8 +107,14 @@ impl<T: Config> Pallet<T> {
match T::XcmRouter::deliver(ticket) {
Ok(_) => {
log::trace!(target: "pallet_funding::hrmp", "HrmpNewChannelOpenRequest: acceptance successfully sent");
project_details.hrmp_channel_status.project_to_polimec = ChannelStatus::Open;
project_details.hrmp_channel_status.polimec_to_project = ChannelStatus::AwaitingAcceptance;
match project_details.migration_type {
MigrationType::ParachainReceiverPallet(ref mut info) => {
info.hrmp_channel_status.project_to_polimec = ChannelStatus::Open;
info.hrmp_channel_status.polimec_to_project = ChannelStatus::AwaitingAcceptance;
},
_ => return Err(XcmError::NoDeal),
}

ProjectsDetails::<T>::insert(project_id, project_details);

Pallet::<T>::deposit_event(Event::<T>::HrmpChannelAccepted {
Expand Down Expand Up @@ -126,11 +144,20 @@ impl<T: Config> Pallet<T> {
log::trace!(target: "pallet_funding::hrmp", "HrmpChannelAccepted received: {:?}", message);
let (project_id, mut project_details) = ProjectsDetails::<T>::iter()
.find(|(_id, details)| {
details.parachain_id == Some(ParaId::from(recipient)) && details.status == FundingSuccessful
matches!(
&details.migration_type,
MigrationType::ParachainReceiverPallet(info) if
info.parachain_id == ParaId::from(recipient) && details.status == FundingSuccessful)
})
.ok_or(XcmError::BadOrigin)?;

project_details.hrmp_channel_status.polimec_to_project = ChannelStatus::Open;
match project_details.migration_type {
MigrationType::ParachainReceiverPallet(ref mut info) => {
info.hrmp_channel_status.polimec_to_project = ChannelStatus::Open;
},
_ => return Err(XcmError::NoDeal),
}

ProjectsDetails::<T>::insert(project_id, project_details);
Pallet::<T>::deposit_event(Event::<T>::HrmpChannelEstablished {
project_id,
Expand All @@ -157,7 +184,10 @@ impl<T: Config> Pallet<T> {
pub fn do_start_migration_readiness_check(caller: &AccountIdOf<T>, project_id: ProjectId) -> DispatchResult {
// * Get variables *
let mut project_details = ProjectsDetails::<T>::get(project_id).ok_or(Error::<T>::ProjectDetailsNotFound)?;
let parachain_id: u32 = project_details.parachain_id.ok_or(Error::<T>::ImpossibleState)?.into();
let MigrationType::ParachainReceiverPallet(ref mut migration_info) = project_details.migration_type else {
return Err(Error::<T>::NotAllowed.into())
};
let parachain_id: u32 = migration_info.parachain_id.into();
let project_multilocation = ParentThen(X1(Parachain(parachain_id)));
let now = <frame_system::Pallet<T>>::block_number();

Expand All @@ -167,17 +197,17 @@ impl<T: Config> Pallet<T> {
// * Validity checks *
ensure!(project_details.status == ProjectStatus::FundingSuccessful, Error::<T>::IncorrectRound);
ensure!(
project_details.hrmp_channel_status ==
migration_info.hrmp_channel_status ==
HRMPChannelStatus {
project_to_polimec: ChannelStatus::Open,
polimec_to_project: ChannelStatus::Open
},
Error::<T>::ChannelNotOpen
);
if project_details.migration_readiness_check.is_none() {
if migration_info.migration_readiness_check.is_none() {
ensure!(caller.clone() == T::PalletId::get().into_account_truncating(), Error::<T>::NotAllowed);
} else if matches!(
project_details.migration_readiness_check,
migration_info.migration_readiness_check,
Some(MigrationReadinessCheck {
holding_check: (_, CheckOutcome::Failed),
pallet_check: (_, CheckOutcome::Failed),
Expand All @@ -203,7 +233,7 @@ impl<T: Config> Pallet<T> {
Here,
);

project_details.migration_readiness_check = Some(MigrationReadinessCheck {
migration_info.migration_readiness_check = Some(MigrationReadinessCheck {
holding_check: (query_id_holdings, CheckOutcome::AwaitingResponse),
pallet_check: (query_id_pallet, CheckOutcome::AwaitingResponse),
});
Expand Down Expand Up @@ -253,13 +283,13 @@ impl<T: Config> Pallet<T> {
) -> DispatchResult {
use xcm::v3::prelude::*;
// TODO: check if this is too low performance. Maybe we want a new map of query_id -> project_id
let (project_id, mut project_details, mut migration_check) = ProjectsDetails::<T>::iter()
let (project_id, mut migration_info, mut project_details) = ProjectsDetails::<T>::iter()
.find_map(|(project_id, details)| {
if let Some(check @ MigrationReadinessCheck { holding_check, pallet_check }) =
details.migration_readiness_check
{
if holding_check.0 == query_id || pallet_check.0 == query_id {
return Some((project_id, details, check));
if let MigrationType::ParachainReceiverPallet(ref info) = details.migration_type {
if let Some(check) = info.migration_readiness_check {
if check.holding_check.0 == query_id || check.pallet_check.0 == query_id {
return Some((project_id, info.clone(), details));
}
}
}
None
Expand All @@ -271,16 +301,18 @@ impl<T: Config> Pallet<T> {
} else {
return Err(Error::<T>::WrongParaId.into());
};
ensure!(migration_info.parachain_id == para_id, Error::<T>::WrongParaId);

let project_metadata = ProjectsMetadata::<T>::get(project_id).ok_or(Error::<T>::ProjectMetadataNotFound)?;
let contribution_tokens_sold =
project_metadata.total_allocation_size.saturating_sub(project_details.remaining_contribution_tokens);
ensure!(project_details.parachain_id == Some(para_id), Error::<T>::WrongParaId);

match (response.clone(), migration_check) {
match (response.clone(), &mut migration_info.migration_readiness_check) {
(
Response::Assets(assets),
MigrationReadinessCheck { holding_check: (_, CheckOutcome::AwaitingResponse), .. },
&mut Some(
ref mut check @ MigrationReadinessCheck { holding_check: (_, CheckOutcome::AwaitingResponse), .. },
),
) => {
let ct_sold_as_u128: u128 = contribution_tokens_sold.try_into().map_err(|_| Error::<T>::BadMath)?;
let assets: Vec<MultiAsset> = assets.into_inner();
Expand All @@ -290,15 +322,15 @@ impl<T: Config> Pallet<T> {
id: Concrete(MultiLocation { parents: 1, interior: X1(Parachain(pid)) }),
fun: Fungible(amount),
} if amount >= ct_sold_as_u128 && pid == u32::from(para_id) => {
migration_check.holding_check.1 = CheckOutcome::Passed(None);
check.holding_check.1 = CheckOutcome::Passed(None);
Self::deposit_event(Event::<T>::MigrationCheckResponseAccepted {
project_id,
query_id,
response,
});
},
_ => {
migration_check.holding_check.1 = CheckOutcome::Failed;
check.holding_check.1 = CheckOutcome::Failed;
Self::deposit_event(Event::<T>::MigrationCheckResponseRejected {
project_id,
query_id,
Expand All @@ -310,7 +342,7 @@ impl<T: Config> Pallet<T> {

(
Response::PalletsInfo(pallets_info),
MigrationReadinessCheck { pallet_check: (_, CheckOutcome::AwaitingResponse), .. },
Some(ref mut check @ MigrationReadinessCheck { pallet_check: (_, CheckOutcome::AwaitingResponse), .. }),
) => {
let expected_module_name: BoundedVec<u8, MaxPalletNameLen> =
BoundedVec::try_from("polimec_receiver".as_bytes().to_vec()).map_err(|_| Error::<T>::NotAllowed)?;
Expand All @@ -319,17 +351,17 @@ impl<T: Config> Pallet<T> {
};
let u8_index: u8 = (*index).try_into().map_err(|_| Error::<T>::NotAllowed)?;
if pallets_info.len() == 1 && module_name == &expected_module_name {
migration_check.pallet_check.1 = CheckOutcome::Passed(Some(u8_index));
check.pallet_check.1 = CheckOutcome::Passed(Some(u8_index));
Self::deposit_event(Event::<T>::MigrationCheckResponseAccepted { project_id, query_id, response });
} else {
migration_check.pallet_check.1 = CheckOutcome::Failed;
check.pallet_check.1 = CheckOutcome::Failed;
Self::deposit_event(Event::<T>::MigrationCheckResponseRejected { project_id, query_id, response });
}
},
_ => return Err(Error::<T>::NotAllowed.into()),
};

project_details.migration_readiness_check = Some(migration_check);
project_details.migration_type = MigrationType::ParachainReceiverPallet(migration_info);
ProjectsDetails::<T>::insert(project_id, project_details);
Ok(())
}
Expand All @@ -338,11 +370,15 @@ impl<T: Config> Pallet<T> {
/// This entails transferring the funds from the Polimec sovereign account to the participant account, and applying
/// a vesting schedule if necessary.
#[transactional]
pub fn do_migrate_one_participant(project_id: ProjectId, participant: AccountIdOf<T>) -> DispatchResult {
pub fn do_receiver_pallet_migrate_for(project_id: ProjectId, participant: AccountIdOf<T>) -> DispatchResult {
// * Get variables *
let project_details = ProjectsDetails::<T>::get(project_id).ok_or(Error::<T>::ProjectDetailsNotFound)?;
let migration_readiness_check = project_details.migration_readiness_check.ok_or(Error::<T>::ChannelNotReady)?;
let project_para_id = project_details.parachain_id.ok_or(Error::<T>::ImpossibleState)?;
let migration_info = match project_details.migration_type {
MigrationType::ParachainReceiverPallet(info) => info,
_ => return Err(Error::<T>::NotAllowed.into()),
};
let migration_readiness_check = migration_info.migration_readiness_check.ok_or(Error::<T>::ChannelNotReady)?;
let project_para_id = migration_info.parachain_id;
let now = <frame_system::Pallet<T>>::block_number();
ensure!(
Self::user_has_no_participations(project_id, participant.clone()),
Expand Down Expand Up @@ -388,9 +424,13 @@ impl<T: Config> Pallet<T> {
let (project_id, participant) =
ActiveMigrationQueue::<T>::take(query_id).ok_or(Error::<T>::NoActiveMigrationsFound)?;
let project_details = ProjectsDetails::<T>::get(project_id).ok_or(Error::<T>::ProjectDetailsNotFound)?;
let migration_info = match project_details.migration_type {
MigrationType::ParachainReceiverPallet(info) => info,
_ => return Err(Error::<T>::NotAllowed.into()),
};

ensure!(
matches!(location, MultiLocation { parents: 1, interior: X1(Parachain(para_id))} if Some(ParaId::from(para_id)) == project_details.parachain_id),
matches!(location, MultiLocation { parents: 1, interior: X1(Parachain(para_id))} if ParaId::from(para_id) == migration_info.parachain_id),
Error::<T>::WrongParaId
);

Expand Down
7 changes: 1 addition & 6 deletions pallets/funding/src/instantiator/chain_interactions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,12 +314,7 @@ impl<
},
usd_bid_on_oversubscription: None,
funding_end_block: None,
parachain_id: None,
migration_readiness_check: None,
hrmp_channel_status: HRMPChannelStatus {
project_to_polimec: crate::ChannelStatus::Closed,
polimec_to_project: crate::ChannelStatus::Closed,
},
migration_type: MigrationType::Offchain,
};
assert_eq!(metadata, expected_metadata);
assert_eq!(details, expected_details);
Expand Down
8 changes: 4 additions & 4 deletions pallets/funding/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1098,7 +1098,7 @@ pub mod pallet {

#[pallet::call_index(22)]
#[pallet::weight(Weight::from_parts(1000, 0))]
pub fn set_para_id_for_project(
pub fn configure_receiver_pallet_migration(
origin: OriginFor<T>,
jwt: UntrustedToken,
project_id: ProjectId,
Expand All @@ -1108,7 +1108,7 @@ pub mod pallet {
T::InvestorOrigin::ensure_origin(origin, &jwt, T::VerifierPublicKey::get())?;
ensure!(investor_type == InvestorType::Institutional, Error::<T>::WrongInvestorType);

Self::do_set_para_id_for_project(&account, project_id, para_id)
Self::do_configure_receiver_pallet_migration(&account, project_id, para_id)
}

#[pallet::call_index(23)]
Expand Down Expand Up @@ -1139,13 +1139,13 @@ pub mod pallet {

#[pallet::call_index(26)]
#[pallet::weight(Weight::from_parts(1000, 0))]
pub fn migrate_one_participant(
pub fn receiver_pallet_migrate_for(
origin: OriginFor<T>,
project_id: ProjectId,
participant: AccountIdOf<T>,
) -> DispatchResult {
let _caller = ensure_signed(origin)?;
Self::do_migrate_one_participant(project_id, participant)
Self::do_receiver_pallet_migrate_for(project_id, participant)
}

#[pallet::call_index(27)]
Expand Down
Loading

0 comments on commit ee1f336

Please sign in to comment.