Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

General storage pallet #243

Merged
merged 3 commits into from
Aug 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
355 changes: 242 additions & 113 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion pallets/carbon-credits-pool/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ pub mod pallet {
project_id,
group_id,
actual,
Default::default()
Default::default(),
)?;

// Update value in storage
Expand Down
8 changes: 4 additions & 4 deletions pallets/carbon-credits/src/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use sp_std::{cmp, convert::TryInto, vec::Vec};
use crate::{
AssetIdLookup, AuthorizedAccounts, BatchGroupOf, BatchRetireDataList, BatchRetireDataOf,
Config, Error, Event, NextAssetId, NextItemId, NextProjectId, Pallet, ProjectCreateParams,
ProjectDetail, Projects, RetiredCarbonCreditsData, RetiredCredits, ShortStringOf
ProjectDetail, Projects, RetiredCarbonCreditsData, RetiredCredits, ShortStringOf,
};

impl<T: Config> Pallet<T> {
Expand Down Expand Up @@ -492,7 +492,7 @@ impl<T: Config> Pallet<T> {
project_id: T::ProjectId,
group_id: T::GroupId,
amount: T::Balance,
reason: ShortStringOf<T>
reason: ShortStringOf<T>,
) -> DispatchResult {
let now = frame_system::Pallet::<T>::block_number();

Expand Down Expand Up @@ -598,7 +598,7 @@ impl<T: Config> Pallet<T> {
retire_data: batch_retire_data_list.clone(),
timestamp: now,
count: amount,
reason : reason.clone()
reason: reason.clone(),
};

//Store the details of retired batches in storage
Expand All @@ -612,7 +612,7 @@ impl<T: Config> Pallet<T> {
account: from,
amount,
retire_data: batch_retire_data_list,
reason
reason,
});

Ok(())
Expand Down
4 changes: 2 additions & 2 deletions pallets/carbon-credits/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ pub mod pallet {
/// Details of the retired token
retire_data: BatchRetireDataList<T>,
/// reason for retirement
reason: ShortStringOf<T>
reason: ShortStringOf<T>,
},
/// A project details has been updated
ProjectUpdated {
Expand Down Expand Up @@ -436,7 +436,7 @@ pub mod pallet {
project_id: T::ProjectId,
group_id: T::GroupId,
amount: T::Balance,
reason: ShortStringOf<T>
reason: ShortStringOf<T>,
) -> DispatchResult {
let sender = ensure_signed(origin)?;
Self::check_kyc_approval(&sender)?;
Expand Down
4 changes: 2 additions & 2 deletions pallets/carbon-credits/src/migration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ pub mod v2 {
RetiredCredits::<T>::translate::<OldRetiredCarbonCreditsData<T>, _>(
|_asset_id, _item_id, old| -> Option<RetiredCarbonCreditsData<T>> {
let converted_data = RetiredCarbonCreditsData {
account : old.account,
account: old.account,
retire_data: old.retire_data,
timestamp: old.timestamp,
count: old.count,
reason: Default::default() // new value
reason: Default::default(), // new value
};
Some(converted_data)
},
Expand Down
8 changes: 7 additions & 1 deletion pallets/carbon-credits/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -995,7 +995,13 @@ fn test_retire_non_minted_project_should_fail() {

// calling retire from a non minted project should fail
assert_noop!(
CarbonCredits::retire(RawOrigin::Signed(3).into(), project_id, group_id, 100u128, Default::default()),
CarbonCredits::retire(
RawOrigin::Signed(3).into(),
project_id,
group_id,
100u128,
Default::default()
),
pallet_assets::Error::<Test>::NoAccount
);
});
Expand Down
2 changes: 1 addition & 1 deletion pallets/carbon-credits/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,5 +153,5 @@ pub struct RetiredCarbonCreditsData<T: pallet::Config> {
/// The total count of credits retired
pub count: T::Balance,
/// Retirement reason
pub reason: ShortStringOf<T>
pub reason: ShortStringOf<T>,
}
41 changes: 41 additions & 0 deletions pallets/general-storage/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
[package]
name = "pallet-general-storage"
version = "4.0.0-dev"
description = "FRAME pallet template for defining custom runtime logic."
authors = ["Substrate DevHub <https://github.com/substrate-developer-hub>"]
homepage = "https://substrate.io"
edition = "2021"
license = "Unlicense"
publish = false
repository = "https://github.com/substrate-developer-hub/substrate-node-template/"

[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

[dependencies]
codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [
"derive",
] }
scale-info = { version = "2.1.1", default-features = false, features = ["derive"] }
frame-benchmarking = { version = "4.0.0-dev", default-features = false, optional = true, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.33" }
frame-support = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.33" }
frame-system = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.33" }

[dev-dependencies]
sp-core = { version = "6.0.0", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.33" }
sp-io = { version = "6.0.0", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.33" }
sp-runtime = { version = "6.0.0", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.33" }
pallet-balances = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.33" }

[features]
default = ["std"]
std = [
"codec/std",
"frame-benchmarking?/std",
"frame-support/std",
"frame-system/std",
"scale-info/std",
"pallet-balances/std"
]
runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks"]
try-runtime = ["frame-support/try-runtime"]
1 change: 1 addition & 0 deletions pallets/general-storage/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
License: Unlicense
141 changes: 141 additions & 0 deletions pallets/general-storage/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
#![cfg_attr(not(feature = "std"), no_std)]

/// Edit this file to define custom logic or remove it if it is not needed.
/// Learn more about FRAME and the core library of Substrate FRAME pallets:
/// <https://docs.substrate.io/reference/frame-pallets/>
pub use pallet::*;

#[cfg(test)]
mod mock;

#[cfg(test)]
mod tests;

#[frame_support::pallet]
pub mod pallet {
use frame_support::{
pallet_prelude::*,
sp_runtime::traits::Zero,
traits::{Currency, ReservableCurrency},
};
use frame_system::pallet_prelude::*;

#[pallet::pallet]
#[pallet::generate_store(pub(super) trait Store)]
pub struct Pallet<T>(_);

/// Configure the pallet by specifying the parameters and types on which it depends.
#[pallet::config]
pub trait Config: frame_system::Config {
/// Because this pallet emits events, it depends on the runtime's definition of an event.
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
// Currency config - this is what the pallet accepts as payment
type Currency: ReservableCurrency<Self::AccountId>;
/// Maximum length of key
type MaxKeyLength: Get<u32>;
/// Maximum length of value
type MaxValueLength: Get<u32>;
/// The deposit charged to store data
type DepositPerByte: Get<CurrencyBalanceOf<Self>>;
}

// -- Types for representing key and value in pallet -- //
/// Type for short strings an descriptions
pub type KeyOf<T> = BoundedVec<u8, <T as Config>::MaxKeyLength>;

/// Type for longer strings and descriptions
pub type ValueOf<T> = BoundedVec<u8, <T as Config>::MaxValueLength>;

pub type CurrencyBalanceOf<T> =
<<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;

// The pallet's runtime storage items.
// https://docs.substrate.io/main-docs/build/runtime-storage/
#[pallet::storage]
#[pallet::getter(fn something)]
// Learn more about declaring storage items:
// https://docs.substrate.io/main-docs/build/runtime-storage/#declaring-storage-items
pub type StoredData<T: Config> =
StorageDoubleMap<_, Blake2_128Concat, T::AccountId, Blake2_128Concat, KeyOf<T>, ValueOf<T>>;

// Pallets use events to inform users when important changes are made.
// https://docs.substrate.io/main-docs/build/events-errors/
#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
/// A new data has been stored on chain
DataStored { key: KeyOf<T>, who: T::AccountId },
/// An existing data has been removed
DataCleared { key: KeyOf<T>, who: T::AccountId },
}

// Errors inform users that something went wrong.
#[pallet::error]
pub enum Error<T> {
/// Error names should be descriptive.
NoDataStored,
/// cannot pass empty key
EmptyInput,
}

// Dispatchable functions allows users to interact with the pallet and invoke state changes.
// These functions materialize as "extrinsics", which are often compared to transactions.
// Dispatchable functions must be annotated with a weight and must return a DispatchResult.
#[pallet::call]
impl<T: Config> Pallet<T> {
/// An example dispatchable that takes a singles value as a parameter, writes the value to
/// storage and emits an event. This function must be dispatched by a signed extrinsic.
#[pallet::weight(10_000 + T::DbWeight::get().writes(1).ref_time())]
pub fn store_data(
origin: OriginFor<T>,
key: KeyOf<T>,
value: ValueOf<T>,
) -> DispatchResult {
let who = ensure_signed(origin)?;

ensure!(!key.len().is_zero() && !value.len().is_zero(), Error::<T>::EmptyInput);

// calculate deposit fee
let deposit_amount = T::DepositPerByte::get() * (value.len() as u32).into();

// reserve deposit fee
T::Currency::reserve(&who, deposit_amount)?;

// Update storage.
<StoredData<T>>::insert(who.clone(), key.clone(), value);

// Emit an event.
Self::deposit_event(Event::DataStored { key, who });

Ok(())
}

/// An example dispatchable that may throw a custom error.
#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1).ref_time())]
pub fn clear_data(origin: OriginFor<T>, key: KeyOf<T>) -> DispatchResult {
let who = ensure_signed(origin)?;

ensure!(!key.len().is_zero(), Error::<T>::EmptyInput);

let data = <StoredData<T>>::get(who.clone(), key.clone());

// does some data exist
ensure!(data.is_some(), Error::<T>::NoDataStored);

// calculate deposit fee
let deposit_amount =
T::DepositPerByte::get() * (data.expect("already checked!").len() as u32).into();

// reserve deposit fee
T::Currency::unreserve(&who, deposit_amount);

// Update storage.
<StoredData<T>>::take(who.clone(), key.clone());

// Emit an event.
Self::deposit_event(Event::DataCleared { key, who });

Ok(())
}
}
}
96 changes: 96 additions & 0 deletions pallets/general-storage/src/mock.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
use crate as pallet_general_storage;
use frame_support::{
parameter_types,
traits::{ConstU16, ConstU64},
};
use frame_system as system;
use sp_core::H256;
use sp_runtime::{
testing::Header,
traits::{BlakeTwo256, IdentityLookup},
};
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
type Block = frame_system::mocking::MockBlock<Test>;

// Configure a mock runtime to test the pallet.
frame_support::construct_runtime!(
pub enum Test where
Block = Block,
NodeBlock = Block,
UncheckedExtrinsic = UncheckedExtrinsic,
{
System: frame_system,
Balances: pallet_balances,
GeneralStorage: pallet_general_storage,
}
);

impl system::Config for Test {
type BaseCallFilter = frame_support::traits::Everything;
type BlockWeights = ();
type BlockLength = ();
type DbWeight = ();
type RuntimeOrigin = RuntimeOrigin;
type RuntimeCall = RuntimeCall;
type Index = u64;
type BlockNumber = u64;
type Hash = H256;
type Hashing = BlakeTwo256;
type AccountId = u64;
type Lookup = IdentityLookup<Self::AccountId>;
type Header = Header;
type RuntimeEvent = RuntimeEvent;
type BlockHashCount = ConstU64<250>;
type Version = ();
type PalletInfo = PalletInfo;
type AccountData = pallet_balances::AccountData<u128>;
type OnNewAccount = ();
type OnKilledAccount = ();
type SystemWeightInfo = ();
type SS58Prefix = ConstU16<42>;
type OnSetCode = ();
type MaxConsumers = frame_support::traits::ConstU32<16>;
}

parameter_types! {
pub const ExistentialDeposit: u64 = 1;
}

impl pallet_balances::Config for Test {
type AccountStore = System;
type Balance = u128;
type DustRemoval = ();
type RuntimeEvent = RuntimeEvent;
type ExistentialDeposit = ExistentialDeposit;
type MaxLocks = ();
type MaxReserves = ();
type ReserveIdentifier = [u8; 8];
type WeightInfo = ();
}

parameter_types! {
pub const MaxKeyLength : u32 = 10;
pub const MaxValueLength : u32 = 100;
pub const DepositPerByte : u128 = 1;
}
impl pallet_general_storage::Config for Test {
type RuntimeEvent = RuntimeEvent;
type Currency = Balances;
type MaxKeyLength = MaxKeyLength;
type MaxValueLength = MaxValueLength;
type DepositPerByte = DepositPerByte;
}

// Build genesis storage according to the mock runtime.
pub fn new_test_ext() -> sp_io::TestExternalities {
let mut t = system::GenesisConfig::default().build_storage::<Test>().unwrap();

let mut ext: sp_io::TestExternalities = t.into();
// need to set block number to 1 to test events
ext.execute_with(|| System::set_block_number(1));
ext
}

pub fn last_event() -> RuntimeEvent {
System::events().pop().expect("Event expected").event
}
Loading