Skip to content

Commit

Permalink
172 housing fund cancel house bidding (#173)
Browse files Browse the repository at this point in the history
* added cancel house bidding functionality

* updated tests
  • Loading branch information
letodunc authored Sep 28, 2022
1 parent dfd1968 commit 259a772
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 1 deletion.
46 changes: 45 additions & 1 deletion pallets/housing_fund/src/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ impl<T: Config> Pallet<T> {
}

// The amount is tagged as reserved in the fund for the account_id
T::LocalCurrency::reserve(&T::PalletId::get().into_account_truncating(), amount)?;
T::LocalCurrency::reserve(&Self::fund_account_id(), amount)?;
fund.reserve(amount);

// The amount is reserved in the pot
Expand Down Expand Up @@ -120,4 +120,48 @@ impl<T: Config> Pallet<T> {
pub fn get_contributions() -> Vec<(AccountIdOf<T>, Contribution<T>)> {
Contributions::<T>::iter().map(|elt| (elt.0, elt.1)).collect()
}

pub fn cancel_house_bidding(nft_collection_id: NftCollectionId<T>, nft_item_id: NftItemId<T>) -> DispatchResultWithPostInfo {
let reservation_wrap = Reservations::<T>::get((nft_collection_id, nft_item_id));

ensure!(reservation_wrap.is_some(), Error::<T>::NoFundReservationFound);

let reservation = reservation_wrap.unwrap();

let contributions_iter = reservation.contributions.iter();

for item in contributions_iter {
let entry = Contributions::<T>::get(item.0.clone());
Contributions::<T>::mutate(item.0.clone(), |val| {
let mut unwrap_val = val.clone().unwrap();
unwrap_val.unreserve_amount(item.1);
let contribution = unwrap_val.clone();
*val = Some(contribution);
});
}

let mut fund = FundBalance::<T>::get();
T::LocalCurrency::unreserve(&Self::fund_account_id(), reservation.amount);
fund.unreserve(reservation.amount);

Reservations::<T>::remove((nft_collection_id, nft_item_id));

// The amount is reserved in the pot
FundBalance::<T>::mutate(|val| {
*val = fund.clone();
});

// Get the block number for timestamp
let block_number = <frame_system::Pallet<T>>::block_number();

// Emit an event.
Self::deposit_event(Event::FundReservationCancelled(
nft_collection_id,
nft_item_id,
reservation.amount,
block_number,
));

Ok(().into())
}
}
3 changes: 3 additions & 0 deletions pallets/housing_fund/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ pub mod pallet {
),
/// Fund reservation succeded
FundReservationSucceeded(T::NftCollectionId, T::NftItemId, BalanceOf<T>, BlockNumberOf<T>),
FundReservationCancelled(T::NftCollectionId, T::NftItemId, BalanceOf<T>, BlockNumberOf<T>),
}

// Errors inform users that something went wrong.
Expand Down Expand Up @@ -144,6 +145,8 @@ pub mod pallet {
NotAnInvestor,
/// Must not have more investor than the max acceppted
NotMoreThanMaxInvestorPerHouse,
/// The reservation doesn't exist in the storage
NoFundReservationFound,
}

#[pallet::call]
Expand Down
7 changes: 7 additions & 0 deletions pallets/housing_fund/src/structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,13 @@ impl<T: Config> FundInfo<T> {
// add the amount to reserved
self.reserved += amount;
}

pub fn unreserve(&mut self, amount: BalanceOf<T>) {
// remove the amount to reserved
self.reserved -= amount;
// add the amount to transferable
self.transferable += amount;
}
}

// Contains amount and timestamp of an account
Expand Down
95 changes: 95 additions & 0 deletions pallets/housing_fund/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,101 @@ fn house_bidding_with_valid_values_should_succeed() {
});
}

#[test]
fn cancel_house_bidding_with_invalid_values_should_fail() {
new_test_ext().execute_with(|| {
// Try to cancel a bidding that doesn't exist
assert_noop!(
HousingFundModule::cancel_house_bidding(1,1),
Error::<Test>::NoFundReservationFound
);
});
}

#[test]
fn cancel_house_bidding_with_valid_values_should_succeed() {
new_test_ext().execute_with(|| {
let fund_account_id = HousingFundModule::fund_account_id();

// Give the investor role to the accounts
assert_ok!(RoleModule::set_role(Origin::signed(1), 1, crate::ROLES::Accounts::INVESTOR));
assert_ok!(RoleModule::set_role(Origin::signed(2), 2, crate::ROLES::Accounts::INVESTOR));

assert_ok!(HousingFundModule::contribute_to_fund(Origin::signed(1), 40));
assert_ok!(HousingFundModule::contribute_to_fund(Origin::signed(2), 40));

assert_ok!(HousingFundModule::house_bidding(
1,
1,
60,
vec![(1, 30), (2, 30)]
));

assert_ok!(HousingFundModule::cancel_house_bidding(1,1));

assert_eq!(
HousingFundModule::fund_balance(),
FundInfo {
total: HousingFundModule::u64_to_balance_option(80).unwrap(),
transferable: HousingFundModule::u64_to_balance_option(80).unwrap(),
reserved: HousingFundModule::u64_to_balance_option(0).unwrap(),
}
);

assert_eq!(
HousingFundModule::contributions(1),
Some(Contribution {
account_id: 1,
available_balance: HousingFundModule::u64_to_balance_option(40).unwrap(),
reserved_balance: HousingFundModule::u64_to_balance_option(0).unwrap(),
contributed_balance: HousingFundModule::u64_to_balance_option(0).unwrap(),
has_withdrawn: false,
block_number: 1,
contributions: vec![ContributionLog {
amount: HousingFundModule::u64_to_balance_option(40).unwrap(),
block_number: 1
}],
withdraws: Vec::new()
})
);

assert_eq!(
HousingFundModule::contributions(2),
Some(Contribution {
account_id: 2,
available_balance: HousingFundModule::u64_to_balance_option(40).unwrap(),
reserved_balance: HousingFundModule::u64_to_balance_option(0).unwrap(),
contributed_balance: HousingFundModule::u64_to_balance_option(0).unwrap(),
has_withdrawn: false,
block_number: 1,
contributions: vec![ContributionLog {
amount: HousingFundModule::u64_to_balance_option(40).unwrap(),
block_number: 1
}],
withdraws: Vec::new()
})
);

assert_eq!(HousingFundModule::reservations((1,1)).is_none(), true);

// Check the amount reserved for the account
assert_eq!(
Balances::reserved_balance(&fund_account_id),
HousingFundModule::u64_to_balance_option(0).unwrap()
);

let event = <frame_system::Pallet<Test>>::events()
.pop()
.expect("Expected at least one EventRecord to be found")
.event;

assert_eq!(
event,
mock::Event::HousingFundModule(crate::Event::FundReservationCancelled(1, 1, 60, 1))
);
});
}

#[test]
fn fund_info_contribute_transferable_should_succeed() {
new_test_ext().execute_with(|| {
Expand Down

0 comments on commit 259a772

Please sign in to comment.