Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
d2a1c7b
Improve naming.
gavofyork Nov 2, 2022
a1748df
More improvements to naming
gavofyork Nov 2, 2022
8394666
Fungible counterpart
gavofyork Nov 2, 2022
c81e4a4
Shared pot instead of reserve
gavofyork Nov 2, 2022
9a78199
Transferable receipts
gavofyork Nov 2, 2022
556aee9
Better naming
gavofyork Nov 2, 2022
326bed5
Use u128 for counterpart
gavofyork Nov 3, 2022
fb9857f
Partial thawing
gavofyork Nov 3, 2022
b232a35
Docs
gavofyork Nov 3, 2022
66fa13b
Remove AdminOrigin
gavofyork Nov 3, 2022
3855ed0
Integrate into Kitchen Sink
gavofyork Nov 3, 2022
ed21e76
Thaw throttling
gavofyork Nov 3, 2022
c2fd94e
Remove todo
gavofyork Nov 3, 2022
ec6b594
Docs
gavofyork Nov 3, 2022
1442179
Fix benchmarks
gavofyork Nov 3, 2022
86ceb01
Building
gavofyork Nov 4, 2022
54609be
Tests work
gavofyork Nov 4, 2022
085996b
New benchmarks
gavofyork Nov 5, 2022
077afbe
Benchmarking tests
gavofyork Nov 5, 2022
3ca6918
Test new defensive_saturating_* functions
ggwpez Nov 5, 2022
25d80d3
fmt
ggwpez Nov 5, 2022
9ea6681
Formatting
gavofyork Nov 6, 2022
be66334
Update frame/nis/src/lib.rs
gavofyork Nov 6, 2022
471c83b
Apply suggestions from code review
gavofyork Nov 6, 2022
c668161
Merge branch 'gav-ref-nis' of github.com:paritytech/substrate into ga…
gavofyork Nov 6, 2022
a44dc75
Events added
gavofyork Nov 6, 2022
f89b093
Fix kitchensink
gavofyork Nov 6, 2022
f5a3e3d
Update frame/nis/src/lib.rs
gavofyork Nov 8, 2022
1474a75
Review niggles
gavofyork Nov 10, 2022
376132d
Merge branch 'gav-ref-nis' of github.com:paritytech/substrate into ga…
gavofyork Nov 11, 2022
bafbdff
Merge remote-tracking branch 'origin/master' into gav-ref-nis
gavofyork Nov 11, 2022
ef9a239
Remove genesis build requirements
gavofyork Nov 11, 2022
207a4b5
Grumbles
gavofyork Nov 14, 2022
e395e84
Merge remote-tracking branch 'origin/master' into gav-ref-nis
gavofyork Nov 14, 2022
6a85012
Fixes
gavofyork Nov 14, 2022
d11f04e
Fixes
gavofyork Nov 14, 2022
8b47006
Fixes
gavofyork Nov 14, 2022
2a59d93
Update frame/nis/src/lib.rs
gavofyork Nov 22, 2022
cd45d8a
Update primitives/runtime/src/traits.rs
gavofyork Nov 22, 2022
d201b05
Merge remote-tracking branch 'origin/master' into gav-ref-nis
gavofyork Nov 22, 2022
990f280
Formatting
gavofyork Nov 22, 2022
15bd0ac
Fixes
gavofyork Nov 23, 2022
9578bf0
Fix node genesis config
ggwpez Nov 23, 2022
ecf4bc1
Fix node chain specs
ggwpez Nov 23, 2022
0a57aed
Use free asset ID as counterpart
ggwpez Nov 23, 2022
6e13e91
Account for rounding errors in fund_deficit bench
ggwpez Nov 23, 2022
45c58b4
clippy
ggwpez Nov 23, 2022
e4499b4
fmt
ggwpez Nov 23, 2022
335ca07
Fix
gavofyork Nov 27, 2022
314728f
Rename
gavofyork Nov 27, 2022
ab31838
Merge branch 'gav-ref-nis' of github.com:paritytech/substrate into ga…
gavofyork Nov 27, 2022
57402c0
Merge remote-tracking branch 'origin/master' into gav-ref-nis
gavofyork Nov 27, 2022
52e6430
Fixes
gavofyork Nov 27, 2022
5817e46
Fixes
gavofyork Nov 27, 2022
fd2575a
Merge branch 'master' into gav-ref-nis
gavofyork Dec 1, 2022
14a4085
Merge remote-tracking branch 'origin/master' into gav-ref-nis
gavofyork Dec 2, 2022
2a18a46
Formatting
gavofyork Dec 2, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Fungible counterpart
  • Loading branch information
gavofyork committed Nov 2, 2022
commit 83946664065fa1588395aa0a4015be9ddcd6f7cf
61 changes: 55 additions & 6 deletions frame/nis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,16 +74,28 @@ mod mock;
mod tests;
pub mod weights;

pub struct WithMaximumOf<A: sp_core::TypedGet>(sp_std::marker::PhantomData<A>);
impl<A: sp_core::TypedGet> sp_runtime::traits::Convert<sp_runtime::Perquintill, A::Type> for WithMaximumOf<A> where
A::Type: Clone + sp_arithmetic::traits::Unsigned + From<u64>,
u64: TryFrom<A::Type>,
{
fn convert(a: sp_runtime::Perquintill) -> A::Type {
a * A::get()
}
}

#[frame_support::pallet]
pub mod pallet {
pub use crate::weights::WeightInfo;
use frame_support::{
pallet_prelude::*,
traits::{Currency, DefensiveSaturating, OnUnbalanced, ReservableCurrency},
traits::{Currency, Defensive, DefensiveSaturating, OnUnbalanced, ReservableCurrency,
fungible::{Inspect as FungibleInspect, Mutate as FungibleMutate}
},
};
use frame_system::pallet_prelude::*;
use sp_arithmetic::{PerThing, Perquintill};
use sp_runtime::traits::{Saturating, Zero};
use sp_runtime::traits::{Saturating, Zero, Convert};
use sp_std::prelude::*;

type BalanceOf<T> =
Expand All @@ -95,8 +107,33 @@ pub mod pallet {
<T as frame_system::Config>::AccountId,
>>::NegativeImbalance;

pub struct NoFungibleReceipt<T>(sp_std::marker::PhantomData<T>);
impl<T> FungibleInspect<T> for NoFungibleReceipt<T> {
type Balance = u32;
fn total_issuance() -> u32 { 0 }
fn minimum_balance() -> u32 { 0 }
fn balance(_who: &T) -> u32 { 0 }
fn reducible_balance(_who: &T, _keep_alive: bool) -> u32 { 0 }
fn can_deposit(_who: &T, _amount: u32, _mint: bool) -> frame_support::traits::tokens::DepositConsequence {
frame_support::traits::tokens::DepositConsequence::Success
}
fn can_withdraw(_who: &T, _amount: u32) -> frame_support::traits::tokens::WithdrawConsequence<u32> {
frame_support::traits::tokens::WithdrawConsequence::Success
}
}
impl<T> FungibleMutate<T> for NoFungibleReceipt<T> {
fn mint_into(_who: &T, _amount: u32) -> DispatchResult { Ok(()) }
fn burn_from(_who: &T, _amount: u32) -> Result<u32, DispatchError> { Ok(0) }
}
impl<T> Convert<Perquintill, u32> for NoFungibleReceipt<T> {
fn convert(_: Perquintill) -> u32 { 0 }
}

#[pallet::config]
pub trait Config: frame_system::Config {
/// Information on runtime weights.
type WeightInfo: WeightInfo;

/// Overarching event type.
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;

Expand Down Expand Up @@ -130,6 +167,13 @@ pub mod pallet {
/// the issuance with which we determine the thawed value of a bond.
type IgnoredIssuance: Get<BalanceOf<Self>>;

type FungibleReceipt: FungibleMutate<Self::AccountId>;

type FungibleEquivalence: Convert<
Perquintill,
<Self::FungibleReceipt as FungibleInspect<Self::AccountId>>::Balance,
>;

/// Number of duration queues in total. This sets the maximum duration supported, which is
/// this value multiplied by `Period`.
#[pallet::constant]
Expand Down Expand Up @@ -172,9 +216,6 @@ pub mod pallet {
/// bids to make into bonds to reach the target.
#[pallet::constant]
type MaxIntakeBids: Get<u32>;

/// Information on runtime weights.
type WeightInfo: WeightInfo;
}

#[pallet::pallet]
Expand Down Expand Up @@ -477,6 +518,10 @@ pub mod pallet {
ensure!(bond.who == who, Error::<T>::NotOwner);
let now = frame_system::Pallet::<T>::block_number();
ensure!(now >= bond.expiry, Error::<T>::NotExpired);

let fung_eq = T::FungibleEquivalence::convert(bond.proportion);
T::FungibleReceipt::burn_from(&who, fung_eq)?;

// Remove it
Active::<T>::remove(index);

Expand Down Expand Up @@ -636,9 +681,13 @@ pub mod pallet {
totals.index += 1;
let e = Event::Issued { index, expiry, who: who.clone(), amount };
Self::deposit_event(e);
let bond = ActiveType { amount, proportion, who, expiry };
let bond = ActiveType { amount, proportion, who: who.clone(), expiry };
Active::<T>::insert(index, bond);

// issue the fungible counterpart
let fung_eq = T::FungibleEquivalence::convert(proportion);
let _ = T::FungibleReceipt::mint_into(&who, fung_eq).defensive();

bids_taken += 1;

if remaining.is_zero() || bids_taken == max_bids {
Expand Down
35 changes: 26 additions & 9 deletions frame/nis/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,18 @@

//! Test environment for NIS pallet.

use crate as pallet_nis;
use crate::{self as pallet_nis, NoFungibleReceipt, WithMaximumOf};

use frame_support::{
ord_parameter_types, parameter_types,
traits::{ConstU16, ConstU32, ConstU64, Currency, GenesisBuild, OnFinalize, OnInitialize},
traits::{ConstU16, ConstU32, ConstU64, Currency, GenesisBuild, OnFinalize, OnInitialize, StorageMapShim},
};
use sp_core::H256;
use sp_runtime::{
testing::Header,
traits::{BlakeTwo256, IdentityLookup},
};
use pallet_balances::{Instance1, Instance2};

type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
type Block = frame_system::mocking::MockBlock<Test>;
Expand All @@ -39,9 +40,10 @@ frame_support::construct_runtime!(
NodeBlock = Block,
UncheckedExtrinsic = UncheckedExtrinsic,
{
System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
Balances: pallet_balances::{Pallet, Call, Config<T>, Storage, Event<T>},
Nis: pallet_nis::{Pallet, Call, Config, Storage, Event<T>},
System: frame_system,
Balances: pallet_balances::<Instance1>,
NisBalances: pallet_balances::<Instance2>,
Nis: pallet_nis,
}
);

Expand Down Expand Up @@ -72,7 +74,7 @@ impl frame_system::Config for Test {
type MaxConsumers = frame_support::traits::ConstU32<16>;
}

impl pallet_balances::Config for Test {
impl pallet_balances::Config<Instance1> for Test {
type Balance = u64;
type DustRemoval = ();
type RuntimeEvent = RuntimeEvent;
Expand All @@ -84,6 +86,19 @@ impl pallet_balances::Config for Test {
type ReserveIdentifier = [u8; 8];
}

impl pallet_balances::Config<Instance2> for Test {
type Balance = u64;
type DustRemoval = ();
type RuntimeEvent = RuntimeEvent;
type ExistentialDeposit = frame_support::traits::ConstU64<1>;
type AccountStore =
StorageMapShim<pallet_balances::Account<Test, Instance2>, frame_system::Provider<Test>, u64, pallet_balances::AccountData<u64>>;
type WeightInfo = ();
type MaxLocks = ();
type MaxReserves = ();
type ReserveIdentifier = [u8; 8];
}

parameter_types! {
pub IgnoredIssuance: u64 = Balances::total_balance(&0); // Account zero is ignored.
}
Expand All @@ -92,28 +107,30 @@ ord_parameter_types! {
}

impl pallet_nis::Config for Test {
type WeightInfo = ();
type RuntimeEvent = RuntimeEvent;
type Currency = Balances;
type CurrencyBalance = <Self as pallet_balances::Config>::Balance;
type CurrencyBalance = <Self as pallet_balances::Config<Instance1>>::Balance;
type AdminOrigin = frame_system::EnsureSignedBy<One, Self::AccountId>;
type Deficit = ();
type Surplus = ();
type IgnoredIssuance = IgnoredIssuance;
type FungibleReceipt = NisBalances;
type FungibleEquivalence = WithMaximumOf<ConstU64<21_000_000u64>>;
type QueueCount = ConstU32<3>;
type MaxQueueLen = ConstU32<3>;
type FifoQueueLen = ConstU32<1>;
type Period = ConstU64<3>;
type MinFreeze = ConstU64<2>;
type IntakePeriod = ConstU64<2>;
type MaxIntakeBids = ConstU32<2>;
type WeightInfo = ();
}

// This function basically just builds a genesis storage key/value store according to
// our desired mockup.
pub fn new_test_ext() -> sp_io::TestExternalities {
let mut t = frame_system::GenesisConfig::default().build_storage::<Test>().unwrap();
pallet_balances::GenesisConfig::<Test> {
pallet_balances::GenesisConfig::<Test, Instance1> {
balances: vec![(1, 100), (2, 100), (3, 100), (4, 100)],
}
.assimilate_storage(&mut t)
Expand Down
18 changes: 16 additions & 2 deletions frame/nis/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@
use super::*;
use crate::{mock::*, Error};
use frame_support::{assert_noop, assert_ok, dispatch::DispatchError, traits::Currency};
use pallet_balances::Error as BalancesError;
use pallet_balances::{Error as BalancesError, Instance1, Instance2};
use sp_arithmetic::Perquintill;
use sp_runtime::TokenError;

#[test]
fn basic_setup_works() {
Expand Down Expand Up @@ -71,7 +72,7 @@ fn place_bid_works() {
assert_noop!(Nis::place_bid(RuntimeOrigin::signed(1), 1, 2), Error::<Test>::AmountTooSmall);
assert_noop!(
Nis::place_bid(RuntimeOrigin::signed(1), 101, 2),
BalancesError::<Test>::InsufficientBalance
BalancesError::<Test, Instance1>::InsufficientBalance
);
assert_noop!(
Nis::place_bid(RuntimeOrigin::signed(1), 10, 4),
Expand Down Expand Up @@ -330,19 +331,32 @@ fn thaw_when_issuance_higher_works() {
assert_ok!(Nis::place_bid(RuntimeOrigin::signed(1), 100, 1));
Nis::enlarge(100, 1);

assert_eq!(NisBalances::free_balance(1), 5_250_000); // (25% of 21m)

// Everybody else's balances goes up by 50%
Balances::make_free_balance_be(&2, 150);
Balances::make_free_balance_be(&3, 150);
Balances::make_free_balance_be(&4, 150);

run_to_block(4);

// Transfer counterpart away...
assert_ok!(NisBalances::transfer(RuntimeOrigin::signed(1), 2, 250_000));
// ...and it's not thawable.
assert_noop!(Nis::thaw(RuntimeOrigin::signed(1), 0), TokenError::NoFunds);

// Transfer counterpart back...
assert_ok!(NisBalances::transfer(RuntimeOrigin::signed(2), 1, 250_000));
// ...and it is.
assert_ok!(Nis::thaw(RuntimeOrigin::signed(1), 0));

assert_eq!(Balances::free_balance(1), 150);
assert_eq!(Balances::reserved_balance(1), 0);
});
}

// TODO: Partial thawing.

#[test]
fn thaw_with_ignored_issuance_works() {
new_test_ext().execute_with(|| {
Expand Down
2 changes: 1 addition & 1 deletion frame/support/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub use tokens::{
Currency, LockIdentifier, LockableCurrency, NamedReservableCurrency, ReservableCurrency,
TotalIssuanceOf, VestingSchedule,
},
fungible, fungibles,
fungible, fungibles, nonfungible, nonfungibles,
imbalance::{Imbalance, OnUnbalanced, SignedImbalance},
BalanceStatus, ExistenceRequirement, Locker, WithdrawReasons,
};
Expand Down
2 changes: 1 addition & 1 deletion frame/support/src/traits/tokens/fungible.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ pub trait Mutate<AccountId>: Inspect<AccountId> {
/// is returned and nothing is changed. If successful, the amount of tokens reduced is returned.
///
/// The default implementation just uses `withdraw` along with `reducible_balance` to ensure
/// that is doesn't fail.
/// that it doesn't fail.
fn slash(who: &AccountId, amount: Self::Balance) -> Result<Self::Balance, DispatchError> {
Self::burn_from(who, Self::reducible_balance(who, false).min(amount))
}
Expand Down