Skip to content
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
1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
[workspace]
resolver = "2"
members = ['exercises/*/*']
[profile.release]
panic = 'unwind'
12 changes: 6 additions & 6 deletions exercises/ex00-testing/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ We created a really simple pallet, `flipper`, that you will have to test.
This pallet allows the users to store a boolean in the storage, calling the `set_value` extrinsic, and then flip its value by calling the `flip_value` extrinsic.

## To do
In `ex00-writing-tests/flipper/src/` you will find a `lib.rs` file that defines the pallet configuration, storage, and dispatchable functions.
In `ex00-writing-tests/flipper/src/tests/` you will find the `mock.rs` file, which simulates the runtime execution. Your test will run against this specific implementation of your pallet. You don't need to update it. All you have to do is write the missing code in the `flipper.rs` file. The goal is to check the correct behavior of the `set_value()` and `flip_value()` functions.
1. Fill the `set_value_ok()` test to ensure `set_value()` is storing the value passed as an argument.
2. Fill the `set_value_err_already_set()` test to ensure that this extrinsic cannot be called twice successfully.
3. Fill the `flip_value_ok()` test to ensure calls to `flip_value()` lead to the boolean value being inverted.
4. Read `flip_function()` code and imagine a scenario that will lead to an error when calling it
In ```ex00-writing-tests/flipper/src/``` you will find a ```.lib``` file that defines the pallet configuration, storage, and dispatchable functions.
In ```ex00-writing-tests/flipper/src/tests/``` you will find the ```mock.rs``` file, which simulates the runtime execution. Your test will run against this specific implementation of your pallet. You don't need to update it. All you have to do is write the missing code in the ```flipper.rs``` file. The goal is to check the correct behavior of the ```set_value()``` and ```flip_value()``` functions.
1. Fill the ```set_value_ok()``` test to ensure ```set_value()``` is storing the value passed as an argument.
2. Fill the ```set_value_err_already_set()``` test to ensure that this extrinsic cannot be called twice successfully.
3. Fill the ```flip_value_ok()``` test to ensure calls to ```flip_value()``` lead to the boolean value being inverted.
4. Read ```flip_function()``` code and imagine a scenario that will lead to an error when calling it

## Some links
* Awesome Rusty: https://github.com/rusty-crewmates/awesome-rusty
Expand Down
11 changes: 6 additions & 5 deletions exercises/ex00-testing/flipper/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features =
scale-info = { version = "2.0.1", default-features = false, features = [
"derive",
] }
frame-support = "38.0.0"
frame-system = "38.0.0"

frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.28" }
frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.28" }

[dev-dependencies]
sp-core = "34.0.0"
sp-io = "38.0.0"
sp-runtime = "39.0.2"
sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.28" }
sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.28" }
sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.28" }

[features]
default = ["std"]
Expand Down
11 changes: 4 additions & 7 deletions exercises/ex00-testing/flipper/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,18 @@ pub use pallet::*;
#[cfg(test)]
mod tests;

#[allow(unexpected_cfgs)] // skip warning "unexpected `cfg` condition value: `try-runtime`"
#[frame_support::pallet]
pub mod pallet {
use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*;

#[pallet::config]
pub trait Config: frame_system::Config {
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
}

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

// The pallet's runtime storage items.
Expand Down Expand Up @@ -52,8 +51,7 @@ pub mod pallet {
impl<T: Config> Pallet<T> {
/// This function sets a value to the Value storage and emits an event, it should be used
/// once, if something is already present in the storage, it returns an error.
#[pallet::weight({0})]
#[pallet::call_index(0)]
#[pallet::weight(0)]
pub fn set_value(origin: OriginFor<T>, value: bool) -> DispatchResult {
// Checks that the extrinsic is signed and gets the signer.
// This function will return an error if the extrinsic isn't signed.
Expand All @@ -79,8 +77,7 @@ pub mod pallet {

/// This function flips the value and emits an event, if there is no value in the storage
/// then it returns an error.
#[pallet::weight({0})]
#[pallet::call_index(1)]
#[pallet::weight(0)]
pub fn flip_value(origin: OriginFor<T>) -> DispatchResult {
let who = ensure_signed(origin)?;

Expand Down
6 changes: 3 additions & 3 deletions exercises/ex00-testing/flipper/src/tests/flipper.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use super::mock::*;
use frame_support::{assert_noop, assert_ok, assert_err};
type Error = crate::Error::<TestRuntime>;
use crate::{pallet, Error};
use frame_support::{assert_noop, assert_ok};

#[test]
fn set_value_ok() {
new_test_ext().execute_with(|| {
assert_ok!(Flipper::set_value(RuntimeOrigin::signed(ALICE), false));
assert_ok!(Flipper::set_value(Origin::signed(ALICE), false));
assert_eq!(Flipper::value(), Some(false));
});
}
Expand Down
40 changes: 20 additions & 20 deletions exercises/ex00-testing/flipper/src/tests/mock.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
use crate as pallet_flipper;
use frame_support::parameter_types;
use frame_system::GenesisConfig;
use sp_core::H256;
use sp_runtime::{
BuildStorage,
traits::{BlakeTwo256, IdentityLookup}, Storage,
testing::Header,
traits::{BlakeTwo256, IdentityLookup},
};

type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<TestRuntime>;
type Block = frame_system::mocking::MockBlock<TestRuntime>;

// Configure a mock runtime to test the pallet.
frame_support::construct_runtime!(
pub enum TestRuntime {
System: frame_system::{Pallet, Call, Config<T>, Storage, Event<T>},
pub enum TestRuntime where
Block = Block,
NodeBlock = Block,
UncheckedExtrinsic = UncheckedExtrinsic,
{
System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
Flipper: pallet_flipper::{Pallet, Call, Storage, Event<T>},
}
);
Expand All @@ -28,41 +32,37 @@ impl frame_system::Config for TestRuntime {
type BaseCallFilter = frame_support::traits::Everything;
type BlockHashCount = BlockHashCount;
type BlockLength = ();
type BlockNumber = u64;
type BlockWeights = ();
type RuntimeCall = RuntimeCall;
type Call = Call;
type DbWeight = ();
type RuntimeEvent = RuntimeEvent;
type Event = Event;
type Hash = H256;
type Hashing = BlakeTwo256;
type Header = Header;
type Index = u64;
type Lookup = IdentityLookup<Self::AccountId>;
type MaxConsumers = frame_support::traits::ConstU32<16>;
type OnKilledAccount = ();
type OnNewAccount = ();
type OnSetCode = ();
type Origin = Origin;
type PalletInfo = PalletInfo;
type SS58Prefix = SS58Prefix;
type SystemWeightInfo = ();
type Version = ();

type RuntimeOrigin = RuntimeOrigin;
type RuntimeTask = ();
type Nonce = u64;
type Block = Block;
type SingleBlockMigrations = ();
type MultiBlockMigrator = ();
type PreInherents = ();
type PostInherents = ();
type PostTransactions = ();
}

impl pallet_flipper::Config for TestRuntime {
type RuntimeEvent = RuntimeEvent;
type Event = Event;
}

// Build genesis storage according to the mock runtime.
pub fn new_test_ext() -> sp_io::TestExternalities {
let storage: Storage = <GenesisConfig<TestRuntime> as BuildStorage>::build_storage(&GenesisConfig::default()).unwrap();
storage.into()
frame_system::GenesisConfig::default()
.build_storage::<TestRuntime>()
.unwrap()
.into()
}

pub const ALICE: u64 = 0;
2 changes: 1 addition & 1 deletion exercises/ex01-pallet-easy/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ In this exercise, you will build a simple fungible asset pallet.

## What to do?

Edit the code in `ex01-pallet-easy/assets/src/lib.rs` until all tests pass.
Edit the code in `ex01-fungible-token/assets/src/lib.rs` until all tests pass.
We placed some helpful comments in the code 😉.

Launch the tests by running:
Expand Down
13 changes: 7 additions & 6 deletions exercises/ex01-pallet-easy/assets/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,15 @@ scale-info = { version = "2.0.1", default-features = false, features = [
"derive",
] }

frame-support = "38.0.0"
frame-system = "38.0.0"
sp-std = "14.0.0"
sp-core = "34.0.0"
frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.28", default-features = false }
frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.28", default-features = false }
sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.28", default-features = false }


[dev-dependencies]
sp-io = "38.0.0"
sp-runtime = "39.0.2"
sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.28" }
sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.28" }
sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.28" }

[features]
default = ["std"]
Expand Down
24 changes: 8 additions & 16 deletions exercises/ex01-pallet-easy/assets/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,24 @@ use types::*;
#[cfg(test)]
mod tests;

#[allow(unexpected_cfgs)] // skip warning "unexpected `cfg` condition value: `try-runtime`"
#[frame_support::pallet]
pub mod pallet {
use super::*;
use frame_support::{pallet_prelude::*, traits::StorageVersion};
use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*;

const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);

/// 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>;
type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;

#[pallet::constant]
type MaxLength: Get<u32>;
}

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

// The pallet's runtime storage items.
Expand Down Expand Up @@ -118,8 +115,7 @@ pub mod pallet {
// Dispatchable functions must be annotated with a weight and must return a DispatchResult.
#[pallet::call]
impl<T: Config> Pallet<T> {
#[pallet::call_index(0)]
#[pallet::weight({0})]
#[pallet::weight(0)]
pub fn create(origin: OriginFor<T>) -> DispatchResult {
let origin = ensure_signed(origin)?;

Expand All @@ -137,8 +133,7 @@ pub mod pallet {
Ok(())
}

#[pallet::call_index(1)]
#[pallet::weight({0})]
#[pallet::weight(0)]
pub fn set_metadata(
origin: OriginFor<T>,
asset_id: AssetId,
Expand All @@ -156,8 +151,7 @@ pub mod pallet {
Ok(())
}

#[pallet::call_index(2)]
#[pallet::weight({0})]
#[pallet::weight(0)]
pub fn mint(
origin: OriginFor<T>,
asset_id: AssetId,
Expand Down Expand Up @@ -189,8 +183,7 @@ pub mod pallet {
Ok(())
}

#[pallet::call_index(3)]
#[pallet::weight({0})]
#[pallet::weight(0)]
pub fn burn(origin: OriginFor<T>, asset_id: AssetId, amount: u128) -> DispatchResult {
// TODO:
// - Ensure the extrinsic origin is a signed transaction.
Expand All @@ -201,8 +194,7 @@ pub mod pallet {
Ok(())
}

#[pallet::call_index(4)]
#[pallet::weight({0})]
#[pallet::weight(0)]
pub fn transfer(
origin: OriginFor<T>,
asset_id: AssetId,
Expand Down
Loading
Loading