I am following following tutorial to write a custom pallet.


When I compile the node, I get following error:

error[E0220]: associated type `BlockNumber` not found for `T`
  --> pallets/template/src/lib.rs:46:62
46 |         StorageMap<_, Blake2_128Concat, T::Hash, (T::AccountId, T::BlockNumber)>;
   |                                                                    ^^^^^^^^^^^ there is a similarly named associated type `BlockNumber` in the trait `BlockNumberProvider`

For more information about this error, try `rustc --explain E0220`.

Here are the contents of my pallet lib.rs file that I trying to compile:

    #![cfg_attr(not(feature = "std"), no_std)]
    // Re-export pallet items so that they can be accessed from the crate namespace.
    pub use pallet::*;
    pub mod pallet {
        use frame_support::pallet_prelude::*;
        use frame_system::pallet_prelude::*;
        #[pallet::generate_store(pub(super) trait Store)]
        pub struct Pallet<T>(_);
        /// Configure the pallet by specifying the parameters and types on which it depends.
        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>;
        // Pallets use events to inform users when important changes are made.
        // Event documentation should end with an array that provides descriptive names for parameters.
        #[pallet::generate_deposit(pub(super) fn deposit_event)]
        pub enum Event<T: Config> {
            /// Event emitted when a claim has been created.
            ClaimCreated { who: T::AccountId, claim: T::Hash },
            /// Event emitted when a claim is revoked by the owner.
            ClaimRevoked { who: T::AccountId, claim: T::Hash },
        pub enum Error<T> {
            /// The claim already exists.
            /// The claim does not exist, so it cannot be revoked.
            /// The claim is owned by another account, so caller can't revoke it.
        pub(super) type Claims<T: Config> =
            StorageMap<_, Blake2_128Concat, T::Hash, (T::AccountId, T::BlockNumber)>;
        // Dispatchable functions allow 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.
        impl<T: Config> Pallet<T> {
            pub fn create_claim(origin: OriginFor<T>, claim: T::Hash) -> DispatchResult {
                // Check that the extrinsic was signed and get the signer.
                // This function will return an error if the extrinsic is not signed.
                let sender = ensure_signed(origin)?;
                // Verify that the specified claim has not already been stored.
                ensure!(!Claims::<T>::contains_key(&claim), Error::<T>::AlreadyClaimed);
                // Get the block number from the FRAME System pallet.
                let current_block = <frame_system::Pallet<T>>::block_number();
                // Store the claim with the sender and block number.
                Claims::<T>::insert(&claim, (&sender, current_block));
                // Emit an event that the claim was created.
                Self::deposit_event(Event::ClaimCreated { who: sender, claim });
            pub fn revoke_claim(origin: OriginFor<T>, claim: T::Hash) -> DispatchResult {
                // Check that the extrinsic was signed and get the signer.
                // This function will return an error if the extrinsic is not signed.
                let sender = ensure_signed(origin)?;
                // Get owner of the claim, if none return an error.
                let (owner, _) = Claims::<T>::get(&claim).ok_or(Error::<T>::NoSuchClaim)?;
                // Verify that sender of the current call is the claim owner.
                ensure!(sender == owner, Error::<T>::NotClaimOwner);
                // Remove claim from storage.
                // Emit an event that the claim was erased.
                Self::deposit_event(Event::ClaimRevoked { who: sender, claim });

1 Answer 1


Check https://github.com/paritytech/polkadot-sdk/commit/5e7b27e98c0b9dacd4b6f0724fd6335106d94101.

Now, you should use BlockNumberFor<T> directly. Because you have already imported it with use frame_system::pallet_prelude::*;.

  • Dear Aurevioc, Thank for the help What I understand is, there is some made to the code base but the tutorial are not yet adjusted accordingly. Since I am facing the very same issue in an other tutorial as well. But I am still not very sure how to use BlockNumberFor<T> in place of BlockNumber<T>. Sep 8 at 17:25
  • 1
    You simply need to replace any occurrence of T::BlockNumber with BlockNumberFor<T>. This is primarily a Rust-related matter. As BlockNumber is no longer a part of T, it has been moved to the Header within T. Additionally, they have introduced a type alias called BlockNumberFor, which corresponds to <HeaderFor<T> as Header>::Number. Essentially, this is equivalent to writing something like T::Header::Number. Sep 8 at 19:32
  • It still gives the following error: type CollectionRandomness: frame_support::traits::Randomness<Self::Hash, BlockNumberFor<T>>; | ^ not found in this scope Sep 11 at 17:34
  • Without the context, I can't help you. Sep 12 at 2:44
  • Here is the github link please: github.com/sayyedkamran/substrate-node-template/blob/… Sep 13 at 17:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.