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

Tutorials > Polkadot SDK > Parachains > Build Custom Pallet > Build the Pallet #232

Merged
merged 15 commits into from
Dec 12, 2024
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]
name = "custom-pallet"
version = "0.1.0"
license.workspace = true
authors.workspace = true
homepage.workspace = true
repository.workspace = true
edition.workspace = true

[dependencies]
codec = { features = ["derive"], workspace = true }
scale-info = { features = ["derive"], workspace = true }
frame-support.workspace = true
frame-system.workspace = true

[features]
default = ["std"]
std = ["codec/std", "frame-support/std", "frame-system/std", "scale-info/std"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#[pallet::call]
impl<T: Config> Pallet<T> {
#[pallet::call_index(0)]
#[pallet::weight(0)]
pub fn set_counter_value(origin: OriginFor<T>, new_value: u32) -> DispatchResult {}

#[pallet::call_index(1)]
#[pallet::weight(0)]
pub fn increment(origin: OriginFor<T>, amount_to_increment: u32) -> DispatchResult {}

#[pallet::call_index(2)]
#[pallet::weight(0)]
pub fn decrement(origin: OriginFor<T>, amount_to_decrement: u32) -> DispatchResult {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<div id="termynal" data-termynal>
<span data-ty="input"><span class="file-path"></span>cargo build --release</span>
<span data-ty>Compiling solochain-template-node</span>
<span data-ty>Finished `release` profile [optimized] target(s) in 27.12s</span>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
#![cfg_attr(not(feature = "std"), no_std)]

pub use pallet::*;

#[frame_support::pallet(dev_mode)]
pub mod pallet {
use super::*;
use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*;

#[pallet::pallet]
pub struct Pallet<T>(_);

// Configuration trait for the pallet
#[pallet::config]
pub trait Config: frame_system::Config {
// Defines the event type for the pallet
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;

// Defines the maximum value the counter can hold
#[pallet::constant]
type CounterMaxValue: Get<u32>;
}

#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
/// The counter value has been set to a new value by Root.
CounterValueSet {
/// The new value set.
counter_value: u32,
},
/// A user has successfully incremented the counter.
CounterIncremented {
/// The new value set.
counter_value: u32,
/// The account who incremented the counter.
who: T::AccountId,
/// The amount by which the counter was incremented.
incremented_amount: u32,
},
/// A user has successfully decremented the counter.
CounterDecremented {
/// The new value set.
counter_value: u32,
/// The account who decremented the counter.
who: T::AccountId,
/// The amount by which the counter was decremented.
decremented_amount: u32,
},
}

/// Storage for the current value of the counter.
#[pallet::storage]
pub type CounterValue<T> = StorageValue<_, u32>;

/// Storage map to track the number of interactions performed by each account.
#[pallet::storage]
pub type UserInteractions<T: Config> = StorageMap<_, Twox64Concat, T::AccountId, u32>;

#[pallet::error]
pub enum Error<T> {
/// The counter value exceeds the maximum allowed value.
CounterValueExceedsMax,
/// The counter value cannot be decremented below zero.
CounterValueBelowZero,
/// Overflow occurred in the counter.
CounterOverflow,
/// Overflow occurred in user interactions.
UserInteractionOverflow,
}

#[pallet::call]
impl<T: Config> Pallet<T> {
/// Set the value of the counter.
///
/// The dispatch origin of this call must be _Root_.
///
/// - `new_value`: The new value to set for the counter.
///
/// Emits `CounterValueSet` event when successful.
#[pallet::call_index(0)]
#[pallet::weight(0)]
pub fn set_counter_value(origin: OriginFor<T>, new_value: u32) -> DispatchResult {
ensure_root(origin)?;

ensure!(
new_value <= T::CounterMaxValue::get(),
Error::<T>::CounterValueExceedsMax
);

CounterValue::<T>::put(new_value);

Self::deposit_event(Event::<T>::CounterValueSet {
counter_value: new_value,
});

Ok(())
}

/// Increment the counter by a specified amount.
///
/// This function can be called by any signed account.
///
/// - `amount_to_increment`: The amount by which to increment the counter.
///
/// Emits `CounterIncremented` event when successful.
#[pallet::call_index(1)]
#[pallet::weight(0)]
pub fn increment(origin: OriginFor<T>, amount_to_increment: u32) -> DispatchResult {
let who = ensure_signed(origin)?;

let current_value = CounterValue::<T>::get().unwrap_or(0);

let new_value = current_value
.checked_add(amount_to_increment)
.ok_or(Error::<T>::CounterOverflow)?;

ensure!(
new_value <= T::CounterMaxValue::get(),
Error::<T>::CounterValueExceedsMax
);

CounterValue::<T>::put(new_value);

UserInteractions::<T>::try_mutate(&who, |interactions| -> Result<_, Error<T>> {
let new_interactions = interactions
.unwrap_or(0)
.checked_add(1)
.ok_or(Error::<T>::UserInteractionOverflow)?;
*interactions = Some(new_interactions); // Store the new value

Ok(())
})?;

Self::deposit_event(Event::<T>::CounterIncremented {
counter_value: new_value,
who,
incremented_amount: amount_to_increment,
});

Ok(())
}

/// Decrement the counter by a specified amount.
///
/// This function can be called by any signed account.
///
/// - `amount_to_decrement`: The amount by which to decrement the counter.
///
/// Emits `CounterDecremented` event when successful.
#[pallet::call_index(2)]
#[pallet::weight(0)]
pub fn decrement(origin: OriginFor<T>, amount_to_decrement: u32) -> DispatchResult {
let who = ensure_signed(origin)?;

let current_value = CounterValue::<T>::get().unwrap_or(0);

let new_value = current_value
.checked_sub(amount_to_decrement)
.ok_or(Error::<T>::CounterValueBelowZero)?;

CounterValue::<T>::put(new_value);

UserInteractions::<T>::try_mutate(&who, |interactions| -> Result<_, Error<T>> {
let new_interactions = interactions
.unwrap_or(0)
.checked_add(1)
.ok_or(Error::<T>::UserInteractionOverflow)?;
*interactions = Some(new_interactions); // Store the new value

Ok(())
})?;

Self::deposit_event(Event::<T>::CounterDecremented {
counter_value: new_value,
who,
decremented_amount: amount_to_decrement,
});

Ok(())
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#![cfg_attr(not(feature = "std"), no_std)]

pub use pallet::*;

#[frame_support::pallet(dev_mode)]
pub mod pallet {
use super::*;
use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*;

#[pallet::pallet]
pub struct Pallet<T>(_);

#[pallet::config]
pub trait Config: frame_system::Config {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ b. Click **Switch** to connect to the respective network

![](/images/tutorials/interoperability/xcm-transfers/from-relaychain-to-parachain/from-relaychain-to-parachain-01.webp)


This reserve-backed transfer method facilitates asset transfers from a local chain to a destination chain by trusting a third party called a reserve to store the real assets. Fees on the destination chain are deducted from the asset specified in the assets vector at the `fee_asset_item` index, covering up to the specified `weight_limit.` The operation fails if the required weight exceeds this limit, potentially putting the transferred assets at risk.

The following steps outline how to execute a reserve-backed transfer from the Polkadot relay chain to the Astar parachain.
Expand Down Expand Up @@ -76,6 +75,7 @@ The following steps outline how to execute a reserve-backed transfer from the Po

3. **beneficiary** - defines the recipient of the assets within the destination context, typically represented as an `AccountId32` value. This example uses the following account present in the destination chain:


```bash
X2mE9hCGX771c3zzV6tPa8U2cDz4U4zkqUdmBrQn83M3cm7
```
Expand All @@ -102,6 +102,7 @@ After submitting the transaction from the relay chain, confirm its success by ch
To programmatically execute the reserve-backed asset transfer between the relay chain and the parachain, you can use [Polkadot API (PAPI)](/develop/toolkit/api-libraries/papi.md){target=\_blank}. PAPI is a robust toolkit that simplifies interactions with Polkadot-based chains. For this project, you'll first need to set up your environment, install necessary dependencies, and create a script to handle the transfer process.

1. Start by creating a folder for your project:

```bash
mkdir reserve-backed-asset-transfer
cd reserve-backed-asset
Expand Down
3 changes: 2 additions & 1 deletion tutorials/polkadot-sdk/parachains/.pages
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ title: Parachains
nav:
- index.md
- local-chain
- connect-to-relay-chain
- connect-to-relay-chain
- build-custom-pallet
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
title: Build Custom Pallet
nav:
- index.md
- 'Build Pallet': build-pallet.md
eshaben marked this conversation as resolved.
Show resolved Hide resolved
Loading