#![cfg(test)]
use super::*;
use frame_support::{assert_noop, assert_ok, error::BadOrigin};
use mock::{Event, *};
use pallet_balances::{BalanceLock, Reasons};
#[test]
fn vesting_from_chain_spec_works() {
ExtBuilder::build().execute_with(|| {
assert_ok!(PalletBalances::ensure_can_withdraw(
&CHARLIE,
10,
WithdrawReasons::TRANSFER,
20
));
assert!(PalletBalances::ensure_can_withdraw(&CHARLIE, 11, WithdrawReasons::TRANSFER, 19).is_err());
assert_eq!(
Vesting::vesting_schedules(&CHARLIE),
vec![VestingSchedule {
start: 2u64,
period: 3u64,
period_count: 4u32,
per_period: 5u64,
}]
);
System::set_block_number(13);
assert_ok!(Vesting::claim(Origin::signed(CHARLIE)));
assert_ok!(PalletBalances::ensure_can_withdraw(
&CHARLIE,
25,
WithdrawReasons::TRANSFER,
5
));
assert!(PalletBalances::ensure_can_withdraw(&CHARLIE, 26, WithdrawReasons::TRANSFER, 4).is_err());
System::set_block_number(14);
assert_ok!(Vesting::claim(Origin::signed(CHARLIE)));
assert_ok!(PalletBalances::ensure_can_withdraw(
&CHARLIE,
30,
WithdrawReasons::TRANSFER,
0
));
});
}
#[test]
fn vested_transfer_works() {
ExtBuilder::build().execute_with(|| {
System::set_block_number(1);
let schedule = VestingSchedule {
start: 0u64,
period: 10u64,
period_count: 1u32,
per_period: 100u64,
};
assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), BOB, schedule.clone()));
assert_eq!(Vesting::vesting_schedules(&BOB), vec![schedule.clone()]);
let vested_event = Event::vesting(crate::Event::VestingScheduleAdded(ALICE, BOB, schedule));
assert!(System::events().iter().any(|record| record.event == vested_event));
});
}
#[test]
fn add_new_vesting_schedule_merges_with_current_locked_balance_and_until() {
ExtBuilder::build().execute_with(|| {
let schedule = VestingSchedule {
start: 0u64,
period: 10u64,
period_count: 2u32,
per_period: 10u64,
};
assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), BOB, schedule));
System::set_block_number(12);
let another_schedule = VestingSchedule {
start: 10u64,
period: 13u64,
period_count: 1u32,
per_period: 7u64,
};
assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), BOB, another_schedule));
assert_eq!(
PalletBalances::locks(&BOB).pop(),
Some(BalanceLock {
id: VESTING_LOCK_ID,
amount: 17u64,
reasons: Reasons::All,
})
);
});
}
#[test]
fn cannot_use_fund_if_not_claimed() {
ExtBuilder::build().execute_with(|| {
let schedule = VestingSchedule {
start: 10u64,
period: 10u64,
period_count: 1u32,
per_period: 50u64,
};
assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), BOB, schedule.clone()));
assert!(PalletBalances::ensure_can_withdraw(&BOB, 1, WithdrawReasons::TRANSFER, 49).is_err());
});
}
#[test]
fn vested_transfer_fails_if_zero_period_or_count() {
ExtBuilder::build().execute_with(|| {
let schedule = VestingSchedule {
start: 1u64,
period: 0u64,
period_count: 1u32,
per_period: 100u64,
};
assert_noop!(
Vesting::vested_transfer(Origin::signed(ALICE), BOB, schedule.clone()),
Error::<Runtime>::ZeroVestingPeriod
);
let schedule = VestingSchedule {
start: 1u64,
period: 1u64,
period_count: 0u32,
per_period: 100u64,
};
assert_noop!(
Vesting::vested_transfer(Origin::signed(ALICE), BOB, schedule.clone()),
Error::<Runtime>::ZeroVestingPeriodCount
);
});
}
#[test]
fn vested_transfer_fails_if_transfer_err() {
ExtBuilder::build().execute_with(|| {
let schedule = VestingSchedule {
start: 1u64,
period: 1u64,
period_count: 1u32,
per_period: 100u64,
};
assert_noop!(
Vesting::vested_transfer(Origin::signed(BOB), ALICE, schedule.clone()),
pallet_balances::Error::<Runtime, _>::InsufficientBalance,
);
});
}
#[test]
fn vested_transfer_fails_if_overflow() {
ExtBuilder::build().execute_with(|| {
let schedule = VestingSchedule {
start: 1u64,
period: 1u64,
period_count: 2u32,
per_period: u64::max_value(),
};
assert_noop!(
Vesting::vested_transfer(Origin::signed(ALICE), BOB, schedule),
Error::<Runtime>::NumOverflow
);
let another_schedule = VestingSchedule {
start: u64::max_value(),
period: 1u64,
period_count: 2u32,
per_period: 1u64,
};
assert_noop!(
Vesting::vested_transfer(Origin::signed(ALICE), BOB, another_schedule),
Error::<Runtime>::NumOverflow
);
});
}
#[test]
fn vested_transfer_fails_if_bad_origin() {
ExtBuilder::build().execute_with(|| {
let schedule = VestingSchedule {
start: 0u64,
period: 10u64,
period_count: 1u32,
per_period: 100u64,
};
assert_noop!(
Vesting::vested_transfer(Origin::signed(CHARLIE), BOB, schedule.clone()),
BadOrigin
);
});
}
#[test]
fn claim_works() {
ExtBuilder::build().execute_with(|| {
let schedule = VestingSchedule {
start: 0u64,
period: 10u64,
period_count: 2u32,
per_period: 10u64,
};
assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), BOB, schedule.clone()));
System::set_block_number(11);
assert!(PalletBalances::transfer(Origin::signed(BOB), ALICE, 10).is_err());
assert_ok!(Vesting::claim(Origin::signed(BOB)));
assert_ok!(PalletBalances::transfer(Origin::signed(BOB), ALICE, 10));
assert!(PalletBalances::transfer(Origin::signed(BOB), ALICE, 1).is_err());
System::set_block_number(21);
assert_ok!(Vesting::claim(Origin::signed(BOB)));
assert_ok!(PalletBalances::transfer(Origin::signed(BOB), ALICE, 10));
assert_eq!(PalletBalances::free_balance(BOB), 0);
assert_eq!(PalletBalances::locks(&BOB), vec![]);
});
}
#[test]
fn update_vesting_schedules_works() {
ExtBuilder::build().execute_with(|| {
let schedule = VestingSchedule {
start: 0u64,
period: 10u64,
period_count: 2u32,
per_period: 10u64,
};
assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), BOB, schedule.clone()));
let updated_schedule = VestingSchedule {
start: 0u64,
period: 20u64,
period_count: 2u32,
per_period: 10u64,
};
assert_ok!(Vesting::update_vesting_schedules(
Origin::root(),
BOB,
vec![updated_schedule]
));
System::set_block_number(11);
assert_ok!(Vesting::claim(Origin::signed(BOB)));
assert!(PalletBalances::transfer(Origin::signed(BOB), ALICE, 1).is_err());
System::set_block_number(21);
assert_ok!(Vesting::claim(Origin::signed(BOB)));
assert_ok!(PalletBalances::transfer(Origin::signed(BOB), ALICE, 10));
});
}
#[test]
fn update_vesting_schedules_fails_if_unexpected_existing_locks() {
ExtBuilder::build().execute_with(|| {
assert_ok!(PalletBalances::transfer(Origin::signed(ALICE), BOB, 1));
PalletBalances::set_lock(*b"prelocks", &BOB, 0u64, WithdrawReasons::all());
});
}
#[test]
fn vested_transfer_check_for_min() {
ExtBuilder::build().execute_with(|| {
let schedule = VestingSchedule {
start: 1u64,
period: 1u64,
period_count: 1u32,
per_period: 3u64,
};
assert_noop!(
Vesting::vested_transfer(Origin::signed(BOB), ALICE, schedule.clone()),
Error::<Runtime>::AmountLow
);
});
}
#[test]
fn multiple_vesting_schedule_claim_works() {
ExtBuilder::build().execute_with(|| {
let schedule = VestingSchedule {
start: 0u64,
period: 10u64,
period_count: 2u32,
per_period: 10u64,
};
assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), BOB, schedule.clone()));
let schedule2 = VestingSchedule {
start: 0u64,
period: 10u64,
period_count: 3u32,
per_period: 10u64,
};
assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), BOB, schedule2.clone()));
assert_eq!(Vesting::vesting_schedules(&BOB), vec![schedule, schedule2.clone()]);
System::set_block_number(21);
assert_ok!(Vesting::claim(Origin::signed(BOB)));
assert_eq!(Vesting::vesting_schedules(&BOB), vec![schedule2]);
System::set_block_number(31);
assert_ok!(Vesting::claim(Origin::signed(BOB)));
assert_eq!(VestingSchedules::<Runtime>::contains_key(&BOB), false);
assert_eq!(PalletBalances::locks(&BOB), vec![]);
});
}