Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make issuer decide migration type #339

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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