Skip to content

Commit ce93385

Browse files
authored
add-modify-vestingInfo-function to the vesting pallet (#450)
* add-modify-vestingInfo-function to the vesting pallet * rewrite set_per_block * fix test * fix time check * fix time check and add unit testing
1 parent 29b108d commit ce93385

File tree

1 file changed

+164
-0
lines changed

1 file changed

+164
-0
lines changed

pallets/vesting/src/lib.rs

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ pub struct VestingInfo<Balance, BlockNumber> {
8484
/// Amount that gets unlocked every block after `starting_block`.
8585
pub per_block: Balance,
8686
/// Starting block for unlocking(vesting).
87+
/// It's relative position to the pallet vesting starting block.
8788
pub starting_block: BlockNumber,
8889
}
8990

@@ -207,6 +208,12 @@ pub mod pallet {
207208
ExistingVestingSchedule,
208209
/// Amount being transferred is too low to create a vesting schedule.
209210
AmountLow,
211+
/// change to the same per_block param
212+
SamePerBlock,
213+
/// VestingStartAt storage is not set
214+
VestingStartAtNotSet,
215+
/// Wrong amount
216+
WrongLockedAmount,
210217
}
211218

212219
#[pallet::hooks]
@@ -397,6 +404,48 @@ pub mod pallet {
397404

398405
Ok(())
399406
}
407+
408+
#[pallet::weight(0)]
409+
pub fn set_vesting_per_block(
410+
origin: OriginFor<T>,
411+
target: <T::Lookup as StaticLookup>::Source,
412+
per_block: BalanceOf<T>,
413+
) -> DispatchResult {
414+
ensure_root(origin)?;
415+
let target = T::Lookup::lookup(target)?;
416+
417+
Self::update_lock(target.clone())?;
418+
let vesting = Self::vesting(&target).ok_or(Error::<T>::NotVesting)?;
419+
420+
ensure!(vesting.per_block != per_block, Error::<T>::SamePerBlock);
421+
422+
let absolute_start =
423+
VestingStartAt::<T>::get().ok_or(Error::<T>::VestingStartAtNotSet)?;
424+
let now = <frame_system::Pallet<T>>::block_number();
425+
426+
let old_start_at = absolute_start.saturating_add(vesting.starting_block);
427+
let remained_vesting =
428+
vesting.locked_at::<T::BlockNumberToBalance>(now, Some(old_start_at));
429+
430+
ensure!(remained_vesting <= vesting.locked, Error::<T>::WrongLockedAmount);
431+
432+
let mut new_start_offset = vesting.starting_block;
433+
if now > old_start_at {
434+
new_start_offset = now - absolute_start;
435+
}
436+
437+
Vesting::<T>::mutate_exists(&target, |info| {
438+
if let Some(ref mut vesting_info) = info {
439+
vesting_info.locked = remained_vesting;
440+
vesting_info.per_block = per_block;
441+
vesting_info.starting_block = new_start_offset;
442+
}
443+
});
444+
445+
Self::update_lock(target)?;
446+
447+
Ok(())
448+
}
400449
}
401450
}
402451

@@ -946,4 +995,119 @@ mod tests {
946995
assert_eq!(user4_free_balance, 256 * 40);
947996
});
948997
}
998+
999+
#[test]
1000+
fn set_vesting_per_block_should_work() {
1001+
ExtBuilder::default().existential_deposit(256).build().execute_with(|| {
1002+
assert_ok!(Vesting::init_vesting_start_at(Origin::root(), 1));
1003+
1004+
let user1_free_balance = Balances::free_balance(&1);
1005+
assert_eq!(user1_free_balance, 256 * 10); // Account 1 has free balance
1006+
let user1_vesting_schedule = VestingInfo {
1007+
locked: 256 * 5,
1008+
per_block: 128, // Vesting over 10 blocks
1009+
starting_block: 0,
1010+
};
1011+
1012+
assert_eq!(Vesting::vesting(&1), Some(user1_vesting_schedule)); // Account 1 has a vesting schedule
1013+
1014+
// Account 1 has only 128 units vested from their illiquid 256 * 5 units at block 1
1015+
assert_eq!(Vesting::vesting_balance(&1), Some(256 * 5));
1016+
1017+
System::set_block_number(6);
1018+
assert_eq!(System::block_number(), 6);
1019+
1020+
// Account 1 has vested by half at the end of block 5
1021+
assert_eq!(Vesting::vesting_balance(&1), Some(128 * 5));
1022+
1023+
// Change the per_block of account 1 to 256
1024+
assert_ok!(Vesting::set_vesting_per_block(Origin::root(), 1, 256));
1025+
1026+
System::set_block_number(7);
1027+
assert_eq!(System::block_number(), 7);
1028+
1029+
let change1_user1_vesting_schedule = VestingInfo {
1030+
locked: 256 * 5 - 128 * 5,
1031+
per_block: 256, // Vesting over 10 blocks
1032+
starting_block: 5,
1033+
};
1034+
1035+
assert_eq!(Vesting::vesting(&1), Some(change1_user1_vesting_schedule)); // Account 1 has a vesting schedule
1036+
assert_eq!(Vesting::vesting_balance(&1), Some(256 * 5 - 128 * 5 - 256));
1037+
1038+
assert_eq!(
1039+
Vesting::set_vesting_per_block(RawOrigin::Root.into(), 1, 256),
1040+
Err(DispatchError::Module { index: 2, error: 3, message: Some("SamePerBlock") })
1041+
);
1042+
1043+
assert_ok!(Vesting::set_vesting_per_block(Origin::root(), 1, 10));
1044+
1045+
System::set_block_number(8);
1046+
assert_eq!(System::block_number(), 8);
1047+
1048+
let change2_user1_vesting_schedule = VestingInfo {
1049+
locked: 256 * 5 - 128 * 5 - 256,
1050+
per_block: 10, // Vesting over 10 blocks
1051+
starting_block: 6,
1052+
};
1053+
1054+
assert_eq!(Vesting::vesting(&1), Some(change2_user1_vesting_schedule));
1055+
assert_eq!(Vesting::vesting_balance(&1), Some(256 * 5 - 128 * 5 - 256 - 10));
1056+
1057+
System::set_block_number(46);
1058+
assert_eq!(System::block_number(), 46);
1059+
1060+
assert_eq!(
1061+
Vesting::set_vesting_per_block(Origin::root(), 1, 20),
1062+
Err(DispatchError::Module { index: 2, error: 0, message: Some("NotVesting") })
1063+
);
1064+
});
1065+
}
1066+
1067+
#[test]
1068+
fn set_vesting_per_block_before_and_after_original_start_block_should_work() {
1069+
ExtBuilder::default().existential_deposit(256).build().execute_with(|| {
1070+
assert_ok!(Vesting::init_vesting_start_at(Origin::root(), 10));
1071+
1072+
let user1_free_balance = Balances::free_balance(&1);
1073+
assert_eq!(user1_free_balance, 256 * 10); // Account 1 has free balance
1074+
let user1_vesting_schedule = VestingInfo {
1075+
locked: 256 * 5,
1076+
per_block: 128, // Vesting over 10 blocks
1077+
starting_block: 0,
1078+
};
1079+
1080+
assert_eq!(Vesting::vesting(&1), Some(user1_vesting_schedule)); // Account 1 has a vesting schedule
1081+
1082+
// Account 1 has only 128 units vested from their illiquid 256 * 5 units at block 1
1083+
assert_eq!(Vesting::vesting_balance(&1), Some(256 * 5));
1084+
1085+
System::set_block_number(6);
1086+
assert_eq!(System::block_number(), 6);
1087+
1088+
// Change the per_block of account 1 to 256
1089+
assert_ok!(Vesting::set_vesting_per_block(Origin::root(), 1, 256));
1090+
1091+
let user2_vesting_schedule = VestingInfo {
1092+
locked: 256 * 5,
1093+
per_block: 256, // Vesting over 10 blocks
1094+
starting_block: 0,
1095+
};
1096+
1097+
assert_eq!(Vesting::vesting(&1), Some(user2_vesting_schedule)); // Account 1 has a vesting schedule
1098+
1099+
System::set_block_number(12);
1100+
assert_eq!(System::block_number(), 12);
1101+
1102+
assert_ok!(Vesting::set_vesting_per_block(Origin::root(), 1, 128));
1103+
1104+
let user3_vesting_schedule = VestingInfo {
1105+
locked: 256 * 5 - 256 * 2,
1106+
per_block: 128, // Vesting over 10 blocks
1107+
starting_block: 2,
1108+
};
1109+
1110+
assert_eq!(Vesting::vesting(&1), Some(user3_vesting_schedule)); // Account 1 has a vesting schedule
1111+
});
1112+
}
9491113
}

0 commit comments

Comments
 (0)