Skip to content

Commit

Permalink
slash behavior on pallet vesting
Browse files Browse the repository at this point in the history
  • Loading branch information
JuaniRios committed Sep 5, 2024
1 parent 1b9300f commit ff81701
Show file tree
Hide file tree
Showing 12 changed files with 337 additions and 0 deletions.
19 changes: 19 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ pallet-sandbox = { path = "pallets/sandbox", default-features = false }
pallet-parachain-staking = { path = "pallets/parachain-staking", default-features = false }
pallet-linear-release = { path = "pallets/linear-release", default-features = false }
polimec-receiver = { path = "pallets/polimec-receiver", default-features = false }
on-slash-vesting = { path = "pallets/on-slash-vesting", default-features = false }

# Internal macros
macros = { path = "macros" }
Expand Down Expand Up @@ -109,6 +110,7 @@ color-print = "0.3.5"
xcm-emulator = { version = "0.12.0", default-features = false }

# Substrate (with default disabled)
impl-trait-for-tuples = { version = "0.2.2", default-features = false }
frame-benchmarking = { version = "35.0.0", default-features = false }
frame-benchmarking-cli = { version = "39.0.0" }
frame-executive = { version = "35.0.0", default-features = false }
Expand Down
1 change: 1 addition & 0 deletions pallets/funding/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ log.workspace = true
variant_count = "1.1.0"

pallet-linear-release.workspace = true
on-slash-vesting.workspace = true

# Substrate dependencies
frame-support.workspace = true
Expand Down
3 changes: 3 additions & 0 deletions pallets/funding/src/functions/6_settlement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use frame_support::{
Get,
},
};
use on_slash_vesting::OnSlash;
use polimec_common::{
migration_types::{MigrationInfo, MigrationOrigin, MigrationStatus, ParticipationType},
ReleaseSchedule,
Expand Down Expand Up @@ -393,6 +394,8 @@ impl<T: Config> Pallet<T> {
Fortitude::Force,
)?;

T::OnSlash::on_slash(&evaluation.evaluator, slashed_amount);

Ok(evaluation.current_plmc_bond.saturating_sub(slashed_amount))
}

Expand Down
4 changes: 4 additions & 0 deletions pallets/funding/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ pub mod pallet {
traits::{OnFinalize, OnIdle, OnInitialize},
};
use frame_system::pallet_prelude::*;
use on_slash_vesting::OnSlash;
use sp_arithmetic::Percent;
use sp_runtime::{
traits::{Convert, ConvertBack, Get},
Expand Down Expand Up @@ -358,6 +359,9 @@ pub mod pallet {

/// Struct holding information about extrinsic weights
type WeightInfo: weights::WeightInfo;

/// Callbacks for dealing with an evaluator slash on other pallets
type OnSlash: OnSlash<AccountIdOf<Self>, Balance>;
}

#[pallet::storage]
Expand Down
1 change: 1 addition & 0 deletions pallets/funding/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,7 @@ impl Config for TestRuntime {
type StringLimit = ConstU32<64>;
type VerifierPublicKey = VerifierPublicKey;
type WeightInfo = weights::SubstrateWeight<TestRuntime>;
type OnSlash = ();
}

// Configure a mock runtime to test the pallet.
Expand Down
42 changes: 42 additions & 0 deletions pallets/on-slash-vesting/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
[package]
name = "on-slash-vesting"
authors.workspace = true
documentation.workspace = true
edition.workspace = true
homepage.workspace = true
license-file.workspace = true
readme.workspace = true
repository.workspace = true
version.workspace = true

[dependencies]
pallet-vesting.workspace = true
impl-trait-for-tuples.workspace = true
frame-support.workspace = true
frame-system.workspace = true
pallet-balances.workspace = true
log.workspace = true
parity-scale-codec.workspace = true
scale-info.workspace = true
sp-runtime.workspace = true
sp-io.workspace = true
serde.workspace = true
[lints]
workspace = true


[features]
default = [ "std" ]

std = [
"pallet-vesting/std",
"frame-support/std",
"frame-system/std",
"pallet-balances/std",
"log/std",
"parity-scale-codec/std",
"scale-info/std",
"sp-runtime/std",
"sp-io/std",
"serde/std",
]
61 changes: 61 additions & 0 deletions pallets/on-slash-vesting/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Ensure we're `no_std` when compiling for Wasm.
#![cfg_attr(not(feature = "std"), no_std)]

#[cfg(test)]
mod mock;
#[cfg(test)]
mod test;

extern crate alloc;
use alloc::vec::Vec;
use frame_support::{
sp_runtime::{traits::Convert, FixedPointNumber, FixedU128},
traits::{Currency, OriginTrait},
};
use pallet_vesting::Vesting;
use sp_runtime::traits::BlockNumberProvider;

pub trait OnSlash<AccountId, Balance: Clone> {
fn on_slash(account: &AccountId, amount: Balance);
}

#[impl_trait_for_tuples::impl_for_tuples(30)]
impl<AccountId, Balance: Clone> OnSlash<AccountId, Balance> for Tuple {
fn on_slash(account: &AccountId, amount: Balance) {
for_tuples!( #( Tuple::on_slash(account, amount.clone()); )* );
}
}

type AccountIdOf<T> = <T as frame_system::Config>::AccountId;
impl<T> OnSlash<AccountIdOf<T>, u128> for pallet_vesting::Pallet<T>
where
T: pallet_vesting::Config,
T::Currency: Currency<AccountIdOf<T>, Balance = u128>,
{
fn on_slash(account: &AccountIdOf<T>, slashed_amount: u128) {
let Some(vesting_schedules) = <Vesting<T>>::get(account) else { return };
let vesting_schedules = vesting_schedules.to_vec();
let mut new_vesting_schedules = Vec::new();
let now = T::BlockNumberProvider::current_block_number();
for schedule in vesting_schedules {
dbg!(schedule);
let total_locked = schedule.locked_at::<T::BlockNumberToBalance>(now).saturating_sub(slashed_amount);
let start_block: u128 = T::BlockNumberToBalance::convert(now);
let end_block: u128 = schedule.ending_block_as_balance::<T::BlockNumberToBalance>();
let duration = end_block.saturating_sub(start_block);
let per_block = FixedU128::from_rational(total_locked, duration).saturating_mul_int(1u128);
let new_schedule = pallet_vesting::VestingInfo::new(total_locked, per_block, now);
if new_schedule.is_valid() {
dbg!(new_schedule);
new_vesting_schedules.push(new_schedule);
}
}
let Ok(new_vesting_schedules) = new_vesting_schedules.try_into() else {
log::error!("Failed to convert new vesting schedules into BoundedVec");
return
};
<Vesting<T>>::set(account, Some(new_vesting_schedules));
let vest_result = <pallet_vesting::Pallet<T>>::vest(T::RuntimeOrigin::signed(account.clone()));
debug_assert!(vest_result.is_ok());
}
}
108 changes: 108 additions & 0 deletions pallets/on-slash-vesting/src/mock.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
use frame_support::{
__private::RuntimeDebug,
derive_impl, parameter_types,
sp_runtime::{traits::IdentityLookup, BuildStorage},
traits::{VariantCount, WithdrawReasons},
};
use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
use scale_info::TypeInfo;
use serde::{Deserialize, Serialize};
use sp_runtime::traits::{ConvertInto, Identity};

frame_support::construct_runtime!(
pub enum TestRuntime {
System: frame_system = 0,
Balances: pallet_balances = 1,
Vesting: pallet_vesting = 2,
}
);
type Block = frame_system::mocking::MockBlock<TestRuntime>;

#[derive(
Encode,
Decode,
Copy,
Clone,
PartialEq,
Eq,
RuntimeDebug,
MaxEncodedLen,
TypeInfo,
Ord,
PartialOrd,
Serialize,
Deserialize,
)]
pub enum MockRuntimeHoldReason {
Reason,
Reason2,
}
impl VariantCount for MockRuntimeHoldReason {
const VARIANT_COUNT: u32 = 2;
}

#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)]
impl frame_system::Config for TestRuntime {
type AccountData = pallet_balances::AccountData<u128>;
type AccountId = u64;
type Block = Block;
type Lookup = IdentityLookup<Self::AccountId>;
}

parameter_types! {
pub const MinVestedTransfer: u64 = 10;
pub UnvestedFundsAllowedWithdrawReasons: WithdrawReasons =
WithdrawReasons::except(WithdrawReasons::TRANSFER | WithdrawReasons::RESERVE);
pub static ExistentialDeposit: u128 = 10u128.pow(7);
}

#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)]
impl pallet_balances::Config for TestRuntime {
type AccountStore = System;
type Balance = u128;
type ExistentialDeposit = ExistentialDeposit;
type RuntimeHoldReason = MockRuntimeHoldReason;
}

impl pallet_vesting::Config for TestRuntime {
#[cfg(feature = "runtime-benchmarks")]
type BenchmarkReason = BenchmarkReason;
type BlockNumberProvider = System;
type BlockNumberToBalance = ConvertInto;
type Currency = Balances;
type MinVestedTransfer = MinVestedTransfer;
type RuntimeEvent = RuntimeEvent;
type UnvestedFundsAllowedWithdrawReasons = UnvestedFundsAllowedWithdrawReasons;
type WeightInfo = ();

const MAX_VESTING_SCHEDULES: u32 = 6;
}

#[derive(Default)]
pub struct ExtBuilder {
pub existential_deposit: u128,
}

impl ExtBuilder {
pub fn existential_deposit(mut self, existential_deposit: u128) -> Self {
self.existential_deposit = existential_deposit;
self
}

pub fn build(self) -> sp_io::TestExternalities {
EXISTENTIAL_DEPOSIT.with(|v| *v.borrow_mut() = self.existential_deposit);
let mut t = frame_system::GenesisConfig::<TestRuntime>::default().build_storage().unwrap();
pallet_balances::GenesisConfig::<TestRuntime> {
balances: vec![
(1, self.existential_deposit),
(2, self.existential_deposit),
(3, self.existential_deposit),
(4, self.existential_deposit),
],
}
.assimilate_storage(&mut t)
.unwrap();

sp_io::TestExternalities::new(t)
}
}
Loading

0 comments on commit ff81701

Please sign in to comment.