Skip to content
Snippets Groups Projects

Oneshot accounts

Merged Pascal Engélibert requested to merge poc-oneshot-accounts into master
2 files
+ 123
3
Compare changes
  • Side-by-side
  • Inline
Files
2
@@ -26,7 +26,7 @@ use frame_support::traits::{OnUnbalanced, StoredMap};
use frame_system::pallet_prelude::*;
use pallet_provide_randomness::RequestId;
use sp_core::H256;
use sp_runtime::traits::{Convert, Saturating, Zero};
use sp_runtime::traits::{Convert, Saturating, StaticLookup, Zero};
#[frame_support::pallet]
pub mod pallet {
@@ -60,6 +60,11 @@ pub mod pallet {
// STORAGE //
#[pallet::storage]
#[pallet::getter(fn oneshot_account)]
pub type OneshotAccounts<T: Config> =
StorageMap<_, Blake2_128Concat, T::AccountId, T::Balance, OptionQuery>;
#[pallet::storage]
#[pallet::getter(fn pending_random_id_assignments)]
pub type PendingRandomIdAssignments<T: Config> =
@@ -133,14 +138,40 @@ pub mod pallet {
/// the account creation price.
/// [who, balance]
ForceDestroy {
balance: T::Balance,
who: T::AccountId,
},
OneshotAccountCreated {
account: T::AccountId,
balance: T::Balance,
creator: T::AccountId,
},
OneshotAccountConsumed {
account: T::AccountId,
balance: T::Balance,
dest: T::AccountId,
},
/// Random id assigned
/// [account_id, random_id]
RandomIdAssigned { who: T::AccountId, random_id: H256 },
}
// ERRORS //
#[pallet::error]
pub enum Error<T> {
/// DestAccountNotExist
DestAccountNotExist,
/// ExistentialDeposit
ExistentialDeposit,
/// InsufficientBalance
InsufficientBalance,
/// OneshotAccouncAlreadyCreated
OneshotAccountAlreadyCreated,
/// OneshotAccountNotExist
OneshotAccountNotExist,
}
// HOOKS //
#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
@@ -217,6 +248,89 @@ pub mod pallet {
total_weight
}
}
// CALLS //
#[pallet::call]
impl<T: Config> Pallet<T> {
#[pallet::weight(500_000_000)]
pub fn create_oneshot_account(
origin: OriginFor<T>,
dest: <T::Lookup as StaticLookup>::Source,
#[pallet::compact] value: T::Balance,
) -> DispatchResult {
let transactor = ensure_signed(origin)?;
let dest = T::Lookup::lookup(dest)?;
ensure!(
value >= T::ExistentialDeposit::get(),
Error::<T>::ExistentialDeposit
);
ensure!(
OneshotAccounts::<T>::get(&dest).is_none(),
Error::<T>::OneshotAccountAlreadyCreated
);
let transactor_data = frame_system::Account::<T>::get(&transactor).data;
let transactor_free_and_reserved = transactor_data
.free
.saturating_add(transactor_data.reserved);
let sufficient_balance = value.saturating_add(T::ExistentialDeposit::get());
ensure!(
transactor_data.free >= value && transactor_free_and_reserved >= sufficient_balance,
Error::<T>::InsufficientBalance
);
frame_system::Account::<T>::mutate(&transactor, |a| a.data.sub_free(value));
OneshotAccounts::<T>::insert(&dest, value);
Self::deposit_event(Event::OneshotAccountCreated {
account: dest,
balance: value,
creator: transactor,
});
Ok(())
}
#[pallet::weight(500_000_000)]
pub fn consume_oneshot_account(
origin: OriginFor<T>,
dest: (bool, <T::Lookup as StaticLookup>::Source),
) -> DispatchResult {
let transactor = ensure_signed(origin)?;
let dest_is_oneshot = dest.0;
let dest = T::Lookup::lookup(dest.1)?;
let value = OneshotAccounts::<T>::take(&transactor)
.ok_or(Error::<T>::OneshotAccountNotExist)?;
if dest_is_oneshot {
ensure!(
OneshotAccounts::<T>::get(&dest).is_none(),
Error::<T>::OneshotAccountAlreadyCreated
);
OneshotAccounts::<T>::insert(&dest, value);
Self::deposit_event(Event::OneshotAccountConsumed {
account: transactor.clone(),
balance: value,
dest: dest.clone(),
});
Self::deposit_event(Event::OneshotAccountCreated {
account: dest,
balance: value,
creator: transactor,
});
} else {
let dest_data = frame_system::Account::<T>::get(&dest).data;
ensure!(dest_data.was_providing(), Error::<T>::DestAccountNotExist);
Self::deposit_event(Event::OneshotAccountConsumed {
account: transactor,
balance: value,
dest,
});
}
Ok(())
}
}
}
impl<T> pallet_provide_randomness::OnFilledRandomness for Pallet<T>
Loading