Skip to content

Commit

Permalink
✌️ Fix project transition event (#368)
Browse files Browse the repository at this point in the history
## What?
- We now emit project transition events
- We do it in the transition project function
- We now use the transition project function for every transition (before was used only till community round)

## How?
- We now use the same project status enum in the event as in the project details
- Events are emitted in the transition project function only
- Transition function is now always used when changing the project state in project_details

## Testing?
- `project_state_transition_event`
  • Loading branch information
JuaniRios authored Aug 23, 2024
1 parent cf671be commit 02e23fd
Show file tree
Hide file tree
Showing 9 changed files with 122 additions and 55 deletions.
6 changes: 3 additions & 3 deletions pallets/funding/src/functions/2_evaluation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ impl<T: Config> Pallet<T> {
project_details,
ProjectStatus::Application,
ProjectStatus::EvaluationRound,
T::EvaluationDuration::get(),
Some(T::EvaluationDuration::get()),
false,
)
}
Expand Down Expand Up @@ -91,7 +91,7 @@ impl<T: Config> Pallet<T> {
project_details,
ProjectStatus::EvaluationRound,
ProjectStatus::AuctionInitializePeriod,
T::AuctionInitializePeriodDuration::get(),
Some(T::AuctionInitializePeriodDuration::get()),
false,
)
// Unsuccessful path
Expand All @@ -104,7 +104,7 @@ impl<T: Config> Pallet<T> {
project_details,
ProjectStatus::EvaluationRound,
ProjectStatus::FundingFailed,
One::one(),
Some(One::one()),
false,
)
}
Expand Down
4 changes: 2 additions & 2 deletions pallets/funding/src/functions/3_auction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ impl<T: Config> Pallet<T> {
project_details,
ProjectStatus::AuctionInitializePeriod,
ProjectStatus::AuctionRound,
T::AuctionOpeningDuration::get(),
Some(T::AuctionOpeningDuration::get()),
skip_round_end_check,
)
}
Expand Down Expand Up @@ -72,7 +72,7 @@ impl<T: Config> Pallet<T> {
updated_project_details,
ProjectStatus::AuctionRound,
ProjectStatus::CommunityRound(now.saturating_add(T::CommunityFundingDuration::get())),
T::CommunityFundingDuration::get() + T::RemainderFundingDuration::get(),
Some(T::CommunityFundingDuration::get() + T::RemainderFundingDuration::get()),
false,
)?;
Ok(PostDispatchInfo {
Expand Down
12 changes: 8 additions & 4 deletions pallets/funding/src/functions/5_funding_end.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,14 @@ impl<T: Config> Pallet<T> {
)
};

let round_end = now.saturating_add(duration).saturating_sub(One::one());
project_details.round_duration.update(Some(now), Some(round_end));
project_details.status = next_status;
ProjectsDetails::<T>::insert(project_id, project_details);
Self::transition_project(
project_id,
project_details.clone(),
project_details.status,
next_status,
Some(duration),
true,
)?;

Ok(PostDispatchInfo { actual_weight: Some(actual_weight), pays_fee: Pays::Yes })
}
Expand Down
45 changes: 26 additions & 19 deletions pallets/funding/src/functions/6_settlement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,11 @@ use sp_runtime::{
impl<T: Config> Pallet<T> {
#[transactional]
pub fn do_start_settlement(project_id: ProjectId) -> DispatchResultWithPostInfo {
// * Get variables *
let mut project_details = ProjectsDetails::<T>::get(project_id).ok_or(Error::<T>::ProjectDetailsNotFound)?;
let token_information =
ProjectsMetadata::<T>::get(project_id).ok_or(Error::<T>::ProjectMetadataNotFound)?.token_information;
let now = <frame_system::Pallet<T>>::block_number();
let round_end_block = project_details.round_duration.end().ok_or(Error::<T>::ImpossibleState)?;

// * Validity checks *
ensure!(
project_details.status == ProjectStatus::FundingSuccessful ||
project_details.status == ProjectStatus::FundingFailed,
Error::<T>::IncorrectRound
);
ensure!(now > round_end_block, Error::<T>::TooEarlyForRound);

// * Calculate new variables *
project_details.funding_end_block = Some(now);

let escrow_account = Self::fund_account_id(project_id);
Expand Down Expand Up @@ -72,16 +61,28 @@ impl<T: Config> Pallet<T> {
liquidity_pools_ct_amount,
)?;

project_details.status = ProjectStatus::SettlementStarted(FundingOutcome::Success);
ProjectsDetails::<T>::insert(project_id, &project_details);
Self::transition_project(
project_id,
project_details,
ProjectStatus::FundingSuccessful,
ProjectStatus::SettlementStarted(FundingOutcome::Success),
None,
false,
)?;

Ok(PostDispatchInfo {
actual_weight: Some(WeightInfoOf::<T>::start_settlement_funding_success()),
pays_fee: Pays::Yes,
})
} else {
project_details.status = ProjectStatus::SettlementStarted(FundingOutcome::Failure);
ProjectsDetails::<T>::insert(project_id, &project_details);
Self::transition_project(
project_id,
project_details,
ProjectStatus::FundingFailed,
ProjectStatus::SettlementStarted(FundingOutcome::Failure),
None,
false,
)?;

Ok(PostDispatchInfo {
actual_weight: Some(WeightInfoOf::<T>::start_settlement_funding_failure()),
Expand Down Expand Up @@ -305,9 +306,9 @@ impl<T: Config> Pallet<T> {
}

pub fn do_mark_project_as_settled(project_id: ProjectId) -> DispatchResult {
let mut project_details = ProjectsDetails::<T>::get(project_id).ok_or(Error::<T>::ProjectDetailsNotFound)?;
let project_details = ProjectsDetails::<T>::get(project_id).ok_or(Error::<T>::ProjectDetailsNotFound)?;
let outcome = match project_details.status {
ProjectStatus::SettlementStarted(outcome) => outcome,
ProjectStatus::SettlementStarted(ref outcome) => outcome.clone(),
_ => return Err(Error::<T>::IncorrectRound.into()),
};

Expand All @@ -323,8 +324,14 @@ impl<T: Config> Pallet<T> {
);

// Mark the project as settled
project_details.status = ProjectStatus::SettlementFinished(outcome);
ProjectsDetails::<T>::insert(project_id, project_details);
Self::transition_project(
project_id,
project_details,
ProjectStatus::SettlementStarted(outcome.clone()),
ProjectStatus::SettlementFinished(outcome),
None,
false,
)?;

Ok(())
}
Expand Down
30 changes: 17 additions & 13 deletions pallets/funding/src/functions/7_ct_migration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@ impl<T: Config> Pallet<T> {
let mut project_details = ProjectsDetails::<T>::get(project_id).ok_or(Error::<T>::ProjectDetailsNotFound)?;

ensure!(project_details.issuer_account == caller, Error::<T>::NotIssuer);
match project_details.status {
ProjectStatus::SettlementFinished(FundingOutcome::Success) => (),
ProjectStatus::FundingSuccessful | ProjectStatus::SettlementStarted(FundingOutcome::Success) =>
return Err(Error::<T>::SettlementNotComplete.into()),
_ => return Err(Error::<T>::IncorrectRound.into()),
}

project_details.migration_type = Some(MigrationType::Offchain);
project_details.status = ProjectStatus::CTMigrationStarted;
ProjectsDetails::<T>::insert(project_id, project_details);

// * Emit events *
Self::transition_project(
project_id,
project_details,
ProjectStatus::SettlementFinished(FundingOutcome::Success),
ProjectStatus::CTMigrationStarted,
None,
false,
)?;

Ok(())
}

Expand Down Expand Up @@ -72,11 +72,15 @@ impl<T: Config> Pallet<T> {
migration_readiness_check: None,
};
project_details.migration_type = Some(MigrationType::Pallet(parachain_receiver_pallet_info));
project_details.status = ProjectStatus::CTMigrationStarted;
ProjectsDetails::<T>::insert(project_id, project_details);

// * Emit events *
Self::deposit_event(Event::PalletMigrationStarted { project_id, para_id });
Self::transition_project(
project_id,
project_details,
ProjectStatus::SettlementFinished(FundingOutcome::Success),
ProjectStatus::CTMigrationStarted,
None,
false,
)?;

Ok(())
}
Expand Down
16 changes: 10 additions & 6 deletions pallets/funding/src/functions/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -393,23 +393,27 @@ impl<T: Config> Pallet<T> {
mut project_details: ProjectDetailsOf<T>,
current_round: ProjectStatus<BlockNumberFor<T>>,
next_round: ProjectStatus<BlockNumberFor<T>>,
round_duration: BlockNumberFor<T>,
maybe_round_duration: Option<BlockNumberFor<T>>,
skip_end_check: bool,
) -> DispatchResult {
/* Verify */
let now = <frame_system::Pallet<T>>::block_number();
ensure!(project_details.round_duration.ended(now) || skip_end_check, Error::<T>::TooEarlyForRound);
ensure!(project_details.status == current_round, Error::<T>::IncorrectRound);

let round_end = now.saturating_add(round_duration).saturating_sub(One::one());
project_details.round_duration.update(Some(now), Some(round_end));
project_details.status = next_round;
let round_end = if let Some(round_duration) = maybe_round_duration {
Some(now.saturating_add(round_duration).saturating_sub(One::one()))
} else {
None
};
project_details.round_duration.update(Some(now), round_end);
project_details.status = next_round.clone();

// * Update storage *
ProjectsDetails::<T>::insert(project_id, project_details);

// // * Emit events *
// Self::deposit_event(Event::ProjectPhaseTransition { project_id, phase: next_round });
// * Emit events *
Self::deposit_event(Event::ProjectPhaseTransition { project_id, phase: next_round });

Ok(())
}
Expand Down
2 changes: 1 addition & 1 deletion pallets/funding/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,7 @@ pub mod pallet {
/// Project transitioned to a new phase.
ProjectPhaseTransition {
project_id: ProjectId,
phase: ProjectPhases,
phase: ProjectStatus<BlockNumberFor<T>>,
},
/// A `bonder` bonded an `amount` of PLMC for `project_id`.
Evaluation {
Expand Down
15 changes: 8 additions & 7 deletions pallets/funding/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,15 +292,16 @@ impl pallet_timestamp::Config for TestRuntime {
pub const HOURS: BlockNumber = 300u64;

// REMARK: In the production configuration we use DAYS instead of HOURS.
// We need all durations to use different times to catch bugs in the tests.
parameter_types! {
pub const EvaluationDuration: BlockNumber = 10u64;
pub const AuctionInitializePeriodDuration: BlockNumber = 10u64;
pub const AuctionOpeningDuration: BlockNumber = 10u64;
pub const AuctionClosingDuration: BlockNumber = 10u64;
pub const CommunityRoundDuration: BlockNumber = 10u64;
pub const RemainderFundingDuration: BlockNumber = 10u64;
pub const ManualAcceptanceDuration: BlockNumber = 10u64;
pub const SuccessToSettlementTime: BlockNumber = 10u64;
pub const AuctionInitializePeriodDuration: BlockNumber = 11u64;
pub const AuctionOpeningDuration: BlockNumber = 12u64;
pub const AuctionClosingDuration: BlockNumber = 13u64;
pub const CommunityRoundDuration: BlockNumber = 14u64;
pub const RemainderFundingDuration: BlockNumber = 15u64;
pub const ManualAcceptanceDuration: BlockNumber = 16u64;
pub const SuccessToSettlementTime: BlockNumber = 17u64;

pub const FundingPalletId: PalletId = PalletId(*b"py/cfund");
pub FeeBrackets: Vec<(Percent, Balance)> = vec![
Expand Down
47 changes: 47 additions & 0 deletions pallets/funding/src/tests/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -366,3 +366,50 @@ mod inner_functions {
assert_eq!(multiplier_25_duration, FixedU128::from_rational(52008, 1000).saturating_mul_int((DAYS * 7) as u64));
}
}

#[test]
fn project_state_transition_event() {
let mut inst = MockInstantiator::new(Some(RefCell::new(new_test_ext())));
let project_id = inst.create_settled_project(
default_project_metadata(ISSUER_1),
ISSUER_1,
None,
default_evaluations(),
default_bids(),
default_community_contributions(),
default_remainder_contributions(),
);

let events = inst.execute(|| System::events());
let transition_events = events
.into_iter()
.filter_map(|event| {
if let RuntimeEvent::PolimecFunding(e @ crate::Event::ProjectPhaseTransition { .. }) = event.event {
Some(e)
} else {
None
}
})
.collect_vec();

let mut desired_transitions = vec![
ProjectStatus::EvaluationRound,
ProjectStatus::AuctionInitializePeriod,
ProjectStatus::AuctionRound,
ProjectStatus::CommunityRound(
EvaluationDuration::get() +
AuctionInitializePeriodDuration::get() +
AuctionOpeningDuration::get() +
CommunityRoundDuration::get() +
1u64,
),
ProjectStatus::FundingSuccessful,
ProjectStatus::SettlementStarted(FundingOutcome::Success),
ProjectStatus::SettlementFinished(FundingOutcome::Success),
]
.into_iter();

transition_events.into_iter().for_each(|event| {
assert_eq!(event, Event::ProjectPhaseTransition { project_id, phase: desired_transitions.next().unwrap() });
});
}

0 comments on commit 02e23fd

Please sign in to comment.