+
```rust
{{#include ./solution/src/lib.rs}}
diff --git a/src/15/solution/solution.diff b/src/15/solution/solution.diff
index a435025c..3b90c013 100644
--- a/src/15/solution/solution.diff
+++ b/src/15/solution/solution.diff
@@ -1,36 +1,19 @@
-diff --git a/src/impls.rs b/src/impls.rs
-index 89c7306..363f5e4 100644
---- a/src/impls.rs
-+++ b/src/impls.rs
-@@ -2,11 +2,10 @@ use super::*;
- use frame::prelude::*;
-
- impl Pallet {
-- /* π§ TODO π§: Update this function signature to include `id` which is type `[u8; 32]`. */
-- pub fn mint(owner: T::AccountId) -> DispatchResult {
-+ pub fn mint(owner: T::AccountId, dna: [u8; 32]) -> DispatchResult {
- let current_count: u32 = CountForKitties::::get();
- let new_count = current_count.checked_add(1).ok_or(Error::::TooManyKitties)?;
-- /* π§ TODO π§: In the `Kitties` map, under the key `id`, insert `()`. */
-+ Kitties::::insert(dna, ());
- CountForKitties::::set(new_count);
- Self::deposit_event(Event::::Created { owner });
- Ok(())
diff --git a/src/lib.rs b/src/lib.rs
-index 3e32e75..c216fa6 100644
+index be05ddb..d4e9d01 100644
--- a/src/lib.rs
+++ b/src/lib.rs
-@@ -38,11 +38,8 @@ pub mod pallet {
- impl Pallet {
- pub fn create_kitty(origin: OriginFor) -> DispatchResult {
- let who = ensure_signed(origin)?;
-- /* π§ TODO π§:
-- - Create `const default_id`, which type `[u8; 32]` and has value `[0u8; 32]`.
-- - Pass `default_id` to the `mint` function as a second parameter.
-- */
-- Self::mint(who)?;
-+ let dna = [0u8; 32];
-+ Self::mint(who, dna)?;
- Ok(())
- }
- }
+@@ -20,12 +20,8 @@ pub mod pallet {
+ #[pallet::storage]
+ pub(super) type CountForKitties = StorageValue;
+
+- /* π§ TODO π§:
+- - Create a new `StorageMap` named `Kitties`.
+- - `Kitties` should be generic over ``.
+- - Set `Key` to `[u8; 32]` to use the kitty id as the key.
+- - Set `Value` to `()` as a placeholder for now.
+- */
++ #[pallet::storage]
++ pub(super) type Kitties = StorageMap;
+
+ #[pallet::event]
+ #[pallet::generate_deposit(pub(super) fn deposit_event)]
diff --git a/src/15/solution/src/impls.rs b/src/15/solution/src/impls.rs
index 363f5e49..d283fd6b 100644
--- a/src/15/solution/src/impls.rs
+++ b/src/15/solution/src/impls.rs
@@ -2,10 +2,9 @@ use super::*;
use frame::prelude::*;
impl Pallet {
- pub fn mint(owner: T::AccountId, dna: [u8; 32]) -> DispatchResult {
+ pub fn mint(owner: T::AccountId) -> DispatchResult {
let current_count: u32 = CountForKitties::::get();
let new_count = current_count.checked_add(1).ok_or(Error::::TooManyKitties)?;
- Kitties::::insert(dna, ());
CountForKitties::::set(new_count);
Self::deposit_event(Event::::Created { owner });
Ok(())
diff --git a/src/15/solution/src/lib.rs b/src/15/solution/src/lib.rs
index c216fa6e..d4e9d017 100644
--- a/src/15/solution/src/lib.rs
+++ b/src/15/solution/src/lib.rs
@@ -38,8 +38,7 @@ pub mod pallet {
impl Pallet {
pub fn create_kitty(origin: OriginFor) -> DispatchResult {
let who = ensure_signed(origin)?;
- let dna = [0u8; 32];
- Self::mint(who, dna)?;
+ Self::mint(who)?;
Ok(())
}
}
diff --git a/src/15/template/README.md b/src/15/template/README.md
index 15924acf..532e7dfe 100644
--- a/src/15/template/README.md
+++ b/src/15/template/README.md
@@ -1,47 +1,76 @@
-# Kitties Map
+# Storage Maps
-Now let's learn to interact with our `Kitties` storage map, and update the map when we `mint` new kitties.
+Now that you have learned everything you need to know about `StorageValue`s, it is time to move on to `StorageMap`s.
-## Basic APIs
+`StorageMap`s are key / value storage items designed for Pallet development.
-This tutorial will only go over just the basic APIs needed to build our Pallet.
+## Syntax
-Check out the [`StorageMap` documentation](https://docs.rs/frame-support/37.0.0/frame_support/storage/types/struct.StorageMap.html) if you want to see the full APIs.
-
-### Reading Storage
-
-To read the current value of a key in a `StorageMap`, you can simply call the [`get(key)`](https://docs.rs/frame-support/37.0.0/frame_support/storage/types/struct.StorageMap.html#method.get) API:
+Declaring a new [`StorageMap`](https://docs.rs/frame-support/37.0.0/frame_support/storage/types/struct.StorageMap.html) is very similar to a `StorageValue`:
```rust
-let my_key: [u8; 32] = [0u8; 32];
-let maybe_value: Option<()> = Kitties::::get(my_key);
+#[pallet::storage]
+pub(super) type Kitties = StorageMap;
```
-Just as the `StorageValue`, you can see this query returns an `Option`, indicating whether there is actually a value under the key.
+Nearly everything is the same, except you need to define a `Key` and `Value`.
+
+Each `Key` can store a separate `Value`, which makes maps super useful.
+
+In this case `[u8; 32]` represents some unique identifier for each Kitty we will store, and `()` is simply a placeholder type for now.
+
+## Conceptual
-Just as before, the most ergonomic way to read a kitty, or throw an error when there is no kitty is to write the following:
+The key difference between a `StorageValue` and a `StorageMap` is:
+
+- A `StorageValue` stores a single value into a single key in the Merkle Trie.
+- A `StorageMap` stores multiple values under different storage keys, all into different places in the Merkle Trie.
+
+Let's clarify further.
+
+Rust has a type `BTreeMap`, which is also a key/value map.
+
+So what would be the difference between:
```rust
-let kitty: () = Kitties::::get(my_key).ok_or(Error::::NoKitty)?;
+#[pallet::storage]
+pub(super) type MyValueMap = StorageValue>;
```
-### Writing Storage
-
-To add a new value to the `StorageMap`, you can simply call the `insert` API:
+and
```rust
-let my_key: [u8; 32] = [0u8; 32];
-Kitties::::insert(my_key, ());
+#[pallet::storage]
+pub(super) type MyMap = StorageMap;
```
-The same behaviors apply to `StorageMap` as a `StorageValue`.
+They both can store the same data, but the `StorageValue` puts all of the data into a single object and stores that all into a single key in the Merkle Trie.
-The [`insert`](https://docs.rs/frame-support/37.0.0/frame_support/storage/types/struct.StorageMap.html#method.insert) API cannot fail. If a value already exists in the map, under the key, we will simply overwrite that value. If you want to check if a value already exists in the map under a key, the most efficient way is to call [`contains_key(key)`](https://docs.rs/frame-support/37.0.0/frame_support/storage/types/struct.StorageMap.html#method.contains_key).
+This means if we want to read just a single key / value pair, we must read ALL data in the whole map, and parse out just the single value we want.
-## Your Turn
+In a `StorageMap`, each value is stored in its own spot in the Merkle Trie, so you are able to read just one key / value on its own. This can be way more efficient for reading just a single item.
+
+However, trying to read multiple items from a `StorageMap` is extremely expensive.
+
+So there is no perfect kind of storage, just tradeoffs.
+
+## Use Cases
+
+`StorageMap`s are really great when we need to store some unique information about a bunch of different things.
-`StorageMap`s are easy!
+The most common example would be trying to store the token balance of all users in your blockchain. In this case, each user has their own `T::AccountId`, and that maps to some balance amount.
-Update the logic in your pallet to insert a new kitty into your `Kitties` map when we call `mint`.
+In our pallet, we use the `StorageMap` to store unique information about each `Kitty` in our pallet.
+
+These use cases make sense because all the logic in our pallet typically touches only one key at a time.
+
+- when you mint a kitty, we create one key / value.
+- when you transfer a kitty, we mutate one key / value.
+- when you put your kitty for sale, you mutate one key / value.
+- etc...
+
+And with the `StorageMap`, we can store a nearly infinite number of different kitties, or at least as many as there are unique keys.
+
+## Your Turn
-For this, you will need to add a second parameter to the `mint` function to pass the unique identifier for the kitty.
+Add the `Kitties` storage map to your project as shown in the template.
diff --git a/src/15/template/src/impls.rs b/src/15/template/src/impls.rs
index 89c7306a..d283fd6b 100644
--- a/src/15/template/src/impls.rs
+++ b/src/15/template/src/impls.rs
@@ -2,11 +2,9 @@ use super::*;
use frame::prelude::*;
impl Pallet {
- /* π§ TODO π§: Update this function signature to include `id` which is type `[u8; 32]`. */
pub fn mint(owner: T::AccountId) -> DispatchResult {
let current_count: u32 = CountForKitties::::get();
let new_count = current_count.checked_add(1).ok_or(Error::::TooManyKitties)?;
- /* π§ TODO π§: In the `Kitties` map, under the key `id`, insert `()`. */
CountForKitties::::set(new_count);
Self::deposit_event(Event::::Created { owner });
Ok(())
diff --git a/src/15/template/src/lib.rs b/src/15/template/src/lib.rs
index 3e32e756..be05ddb9 100644
--- a/src/15/template/src/lib.rs
+++ b/src/15/template/src/lib.rs
@@ -20,8 +20,12 @@ pub mod pallet {
#[pallet::storage]
pub(super) type CountForKitties