mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 11:41:04 +00:00
Adding vesting logic to claims (#637)
* Adding vesting logic to claims * Add genesis * Update runtime/src/claims.rs Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com> * Bump spec * Update runtime/src/claims.rs
This commit is contained in:
committed by
Gavin Wood
parent
675ca2e258
commit
b637a77249
@@ -20,7 +20,7 @@ use rstd::prelude::*;
|
|||||||
use sp_io::{hashing::keccak_256, crypto::secp256k1_ecdsa_recover};
|
use sp_io::{hashing::keccak_256, crypto::secp256k1_ecdsa_recover};
|
||||||
use frame_support::{decl_event, decl_storage, decl_module};
|
use frame_support::{decl_event, decl_storage, decl_module};
|
||||||
use frame_support::weights::SimpleDispatchInfo;
|
use frame_support::weights::SimpleDispatchInfo;
|
||||||
use frame_support::traits::{Currency, Get};
|
use frame_support::traits::{Currency, Get, VestingCurrency};
|
||||||
use system::{ensure_root, ensure_none};
|
use system::{ensure_root, ensure_none};
|
||||||
use codec::{Encode, Decode};
|
use codec::{Encode, Decode};
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
@@ -41,7 +41,8 @@ type BalanceOf<T> = <<T as Trait>::Currency as Currency<<T as system::Trait>::Ac
|
|||||||
pub trait Trait: system::Trait {
|
pub trait Trait: system::Trait {
|
||||||
/// The overarching event type.
|
/// The overarching event type.
|
||||||
type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
|
type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
|
||||||
type Currency: Currency<Self::AccountId>;
|
type Currency: Currency<Self::AccountId>
|
||||||
|
+ VestingCurrency<Self::AccountId, Moment=Self::BlockNumber>;
|
||||||
type Prefix: Get<&'static [u8]>;
|
type Prefix: Get<&'static [u8]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,6 +113,11 @@ decl_storage! {
|
|||||||
Total get(total) build(|config: &GenesisConfig<T>| {
|
Total get(total) build(|config: &GenesisConfig<T>| {
|
||||||
config.claims.iter().fold(Zero::zero(), |acc: BalanceOf<T>, &(_, n)| acc + n)
|
config.claims.iter().fold(Zero::zero(), |acc: BalanceOf<T>, &(_, n)| acc + n)
|
||||||
}): BalanceOf<T>;
|
}): BalanceOf<T>;
|
||||||
|
/// Vesting schedule for a claim.
|
||||||
|
/// First balance is the total amount that should be held for vesting.
|
||||||
|
/// Second balance is how much should be unlocked per block.
|
||||||
|
/// The block number is when the vesting should start.
|
||||||
|
Vesting get(vesting) config(): map EthereumAddress => Option<(BalanceOf<T>, BalanceOf<T>, T::BlockNumber)>;
|
||||||
}
|
}
|
||||||
add_extra_genesis {
|
add_extra_genesis {
|
||||||
config(claims): Vec<(EthereumAddress, BalanceOf<T>)>;
|
config(claims): Vec<(EthereumAddress, BalanceOf<T>)>;
|
||||||
@@ -135,9 +141,19 @@ decl_module! {
|
|||||||
let signer = Self::eth_recover(ðereum_signature, &data)
|
let signer = Self::eth_recover(ðereum_signature, &data)
|
||||||
.ok_or("Invalid Ethereum signature")?;
|
.ok_or("Invalid Ethereum signature")?;
|
||||||
|
|
||||||
let balance_due = <Claims<T>>::take(&signer)
|
let balance_due = <Claims<T>>::get(&signer)
|
||||||
.ok_or("Ethereum address has no claim")?;
|
.ok_or("Ethereum address has no claim")?;
|
||||||
|
|
||||||
|
// Check if this claim should have a vesting schedule.
|
||||||
|
if let Some(vs) = <Vesting<T>>::get(&signer) {
|
||||||
|
// If this fails, destination account already has a vesting schedule
|
||||||
|
// applied to it, and this claim should not be processed.
|
||||||
|
T::Currency::add_vesting_schedule(&dest, vs.0, vs.1, vs.2)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
<Claims<T>>::remove(&signer);
|
||||||
|
<Vesting<T>>::remove(&signer);
|
||||||
|
|
||||||
<Total<T>>::mutate(|t| if *t < balance_due {
|
<Total<T>>::mutate(|t| if *t < balance_due {
|
||||||
panic!("Logic error: Pot less than the total of claims!")
|
panic!("Logic error: Pot less than the total of claims!")
|
||||||
} else {
|
} else {
|
||||||
@@ -152,11 +168,18 @@ decl_module! {
|
|||||||
|
|
||||||
/// Add a new claim, if you are root.
|
/// Add a new claim, if you are root.
|
||||||
#[weight = SimpleDispatchInfo::FreeOperational]
|
#[weight = SimpleDispatchInfo::FreeOperational]
|
||||||
fn mint_claim(origin, who: EthereumAddress, value: BalanceOf<T>) {
|
fn mint_claim(origin,
|
||||||
|
who: EthereumAddress,
|
||||||
|
value: BalanceOf<T>,
|
||||||
|
vesting_schedule: Option<(BalanceOf<T>, BalanceOf<T>, T::BlockNumber)>,
|
||||||
|
) {
|
||||||
ensure_root(origin)?;
|
ensure_root(origin)?;
|
||||||
|
|
||||||
<Total<T>>::mutate(|t| *t += value);
|
<Total<T>>::mutate(|t| *t += value);
|
||||||
<Claims<T>>::insert(who, value);
|
<Claims<T>>::insert(who, value);
|
||||||
|
if let Some(vs) = vesting_schedule {
|
||||||
|
<Vesting<T>>::insert(who, vs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -345,6 +368,7 @@ mod tests {
|
|||||||
balances::GenesisConfig::<Test>::default().assimilate_storage(&mut t).unwrap();
|
balances::GenesisConfig::<Test>::default().assimilate_storage(&mut t).unwrap();
|
||||||
GenesisConfig::<Test>{
|
GenesisConfig::<Test>{
|
||||||
claims: vec![(eth(&alice()), 100)],
|
claims: vec![(eth(&alice()), 100)],
|
||||||
|
vesting: vec![(eth(&alice()), (50, 10, 1))],
|
||||||
}.assimilate_storage(&mut t).unwrap();
|
}.assimilate_storage(&mut t).unwrap();
|
||||||
t.into()
|
t.into()
|
||||||
}
|
}
|
||||||
@@ -355,6 +379,7 @@ mod tests {
|
|||||||
assert_eq!(Claims::total(), 100);
|
assert_eq!(Claims::total(), 100);
|
||||||
assert_eq!(Claims::claims(ð(&alice())), Some(100));
|
assert_eq!(Claims::claims(ð(&alice())), Some(100));
|
||||||
assert_eq!(Claims::claims(&EthereumAddress::default()), None);
|
assert_eq!(Claims::claims(&EthereumAddress::default()), None);
|
||||||
|
assert_eq!(Claims::vesting(ð(&alice())), Some((50, 10, 1)));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,21 +398,45 @@ mod tests {
|
|||||||
assert_eq!(Balances::free_balance(&42), 0);
|
assert_eq!(Balances::free_balance(&42), 0);
|
||||||
assert_ok!(Claims::claim(Origin::NONE, 42, sig(&alice(), &42u64.encode())));
|
assert_ok!(Claims::claim(Origin::NONE, 42, sig(&alice(), &42u64.encode())));
|
||||||
assert_eq!(Balances::free_balance(&42), 100);
|
assert_eq!(Balances::free_balance(&42), 100);
|
||||||
|
assert_eq!(Balances::vesting_balance(&42), 50);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn add_claim_works() {
|
fn add_claim_works() {
|
||||||
new_test_ext().execute_with(|| {
|
new_test_ext().execute_with(|| {
|
||||||
assert_noop!(Claims::mint_claim(Origin::signed(42), eth(&bob()), 200), "RequireRootOrigin");
|
assert_noop!(
|
||||||
|
Claims::mint_claim(Origin::signed(42), eth(&bob()), 200, None),
|
||||||
|
"RequireRootOrigin"
|
||||||
|
);
|
||||||
assert_eq!(Balances::free_balance(&42), 0);
|
assert_eq!(Balances::free_balance(&42), 0);
|
||||||
assert_noop!(
|
assert_noop!(
|
||||||
Claims::claim(Origin::NONE, 69, sig(&bob(), &69u64.encode())),
|
Claims::claim(Origin::NONE, 69, sig(&bob(), &69u64.encode())),
|
||||||
"Ethereum address has no claim"
|
"Ethereum address has no claim"
|
||||||
);
|
);
|
||||||
assert_ok!(Claims::mint_claim(Origin::ROOT, eth(&bob()), 200));
|
assert_ok!(Claims::mint_claim(Origin::ROOT, eth(&bob()), 200, None));
|
||||||
assert_ok!(Claims::claim(Origin::NONE, 69, sig(&bob(), &69u64.encode())));
|
assert_ok!(Claims::claim(Origin::NONE, 69, sig(&bob(), &69u64.encode())));
|
||||||
assert_eq!(Balances::free_balance(&69), 200);
|
assert_eq!(Balances::free_balance(&69), 200);
|
||||||
|
assert_eq!(Balances::vesting_balance(&69), 0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn add_claim_with_vesting_works() {
|
||||||
|
new_test_ext().execute_with(|| {
|
||||||
|
assert_noop!(
|
||||||
|
Claims::mint_claim(Origin::signed(42), eth(&bob()), 200, Some((50, 10, 1))),
|
||||||
|
"RequireRootOrigin"
|
||||||
|
);
|
||||||
|
assert_eq!(Balances::free_balance(&42), 0);
|
||||||
|
assert_noop!(
|
||||||
|
Claims::claim(Origin::NONE, 69, sig(&bob(), &69u64.encode())),
|
||||||
|
"Ethereum address has no claim"
|
||||||
|
);
|
||||||
|
assert_ok!(Claims::mint_claim(Origin::ROOT, eth(&bob()), 200, Some((50, 10, 1))));
|
||||||
|
assert_ok!(Claims::claim(Origin::NONE, 69, sig(&bob(), &69u64.encode())));
|
||||||
|
assert_eq!(Balances::free_balance(&69), 200);
|
||||||
|
assert_eq!(Balances::vesting_balance(&69), 50);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
|
|||||||
spec_name: create_runtime_str!("kusama"),
|
spec_name: create_runtime_str!("kusama"),
|
||||||
impl_name: create_runtime_str!("parity-kusama"),
|
impl_name: create_runtime_str!("parity-kusama"),
|
||||||
authoring_version: 2,
|
authoring_version: 2,
|
||||||
spec_version: 1023,
|
spec_version: 1024,
|
||||||
impl_version: 0,
|
impl_version: 0,
|
||||||
apis: RUNTIME_API_VERSIONS,
|
apis: RUNTIME_API_VERSIONS,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -199,6 +199,7 @@ fn staging_testnet_config_genesis() -> GenesisConfig {
|
|||||||
}),
|
}),
|
||||||
claims: Some(ClaimsConfig {
|
claims: Some(ClaimsConfig {
|
||||||
claims: vec![],
|
claims: vec![],
|
||||||
|
vesting: vec![],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -338,6 +339,7 @@ pub fn testnet_genesis(
|
|||||||
}),
|
}),
|
||||||
claims: Some(ClaimsConfig {
|
claims: Some(ClaimsConfig {
|
||||||
claims: vec![],
|
claims: vec![],
|
||||||
|
vesting: vec![],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user