0

I'm currently trying this substrate tutorial, but it got stuck.

Following the tutorial, I coded lib.rs file like this.

#![cfg_attr(not(feature = "std"), no_std)]
pub use pallet::*;

#[frame_support::pallet]
pub mod pallet {
    use frame_support::pallet_prelude::*;
    use frame_system::pallet_prelude::*;
    use sp_std::vec::Vec; // Step 3.1 will include this in `Cargo.toml`

    #[pallet::config]
    pub trait Config: frame_system::Config {
        type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
    }
    #[pallet::event]
    #[pallet::generate_deposit(pub(super) fn deposit_event)]
    pub enum Event<T: Config> {
        ClaimCreated(T::AccountId, Vec<u8>),
        ClaimRevoked(T::AccountId, Vec<u8>),
    }
    #[pallet::error]
    pub enum Error<T> {
        ProofAlreadyClaimed,
        NoSuchProof,
        NotProofOwner,
    }
    #[pallet::pallet]
    #[pallet::generate_store(pub(super) trait Store)]
    pub struct Pallet<T>(_);

    #[pallet::storage]
    pub(super) type Proofs<T: Config> = StorageMap<_, Blake2_128Concat, Vec<u8>, (T::AccountId, T::BlockNumber), ValueQuery>;
    #[pallet::hooks]
    impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {}
    #[pallet::call]
    impl<T: Config> Pallet<T> {
        #[pallet::weight(1_000)]
        pub fn create_claim(
            origin: OriginFor<T>,
            proof: Vec<u8>,
        ) -> DispatchResult {
            let sender = ensure_signed(origin)?;
            ensure!(!Proofs::<T>::contains_key(&proof), Error::<T>::ProofAlreadyClaimed);
            let current_block = <frame_system::Pallet<T>>::block_number();
            Proofs::<T>::insert(&proof, (&sender, current_block));
            Self::deposit_event(Event::ClaimCreated(sender, proof));
            Ok(())
        }
        #[pallet::weight(10_000)]
        pub fn revoke_claim(
            origin: OriginFor<T>,
            proof: Vec<u8>,
        ) -> DispatchResult {
            let sender = ensure_signed(origin)?;
            ensure!(Proofs::<T>::contains_key(&proof),Error::<T>::NoSuchProof);
            let (owner, _) = Proofs::<T>::get(&proof);
            ensure!(sender == owner, Error::<T>::NotProofOwner);
            Proofs::<T>::remove(&proof);
            Self::deposit_event(Event::ClaimRevoked(sender, proof));
            Ok(())
        }
    }
}

Cargo.toml file is like this.

[package]
name = "pallet-template"
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-support = { default-features = false, version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.26"}
frame-system = { default-features = false, version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.26" }
frame-benchmarking = { default-features = false, version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.26", optional = true }

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

[dependencies.sp-std]
default-features = false
git = 'https://github.com/paritytech/substrate.git'
branch = 'polkadot-v0.9.26' 

[features]
default = ["std"]
std = [
  "sp-std/std",
    "codec/std",
    "scale-info/std",
    "frame-support/std",
    "frame-system/std",
    "frame-benchmarking/std",
]

runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks"]
try-runtime = ["frame-support/try-runtime"]

And I used command "cargo check -p node-template-runtime". But I got an Error like this.

ensure!(!Proofs::<T>::contains_key(&proof), Error::<T>::ProofAlreadyClaimed);
                      ^^^^^^^^^^^^ function or associated item cannot be called on 
`frame_support::pallet_prelude::StorageMap<_GeneratedPrefixForStorageProofs<T>, frame_support::Blake2_128Concat, Vec<u8>, (<T as frame_system::Config>::AccountId, <T as frame_system::Config>::BlockNumber), frame_support::pallet_prelude::ValueQuery>` due to unsatisfied trait bounds

Proofs::<T>::insert(&proof, (&sender, current_block));
             ^^^^^^ function or associated item cannot be called on `frame_support::pallet_prelude::StorageMap<_GeneratedPrefixForStorageProofs<T>, frame_support::Blake2_128Concat, Vec<u8>, (<T as frame_system::Config>::AccountId, <T as frame_system::Config>::BlockNumber), frame_support::pallet_prelude::ValueQuery>` due to unsatisfied trait bounds

ensure!(Proofs::<T>::contains_key(&proof),Error::<T>::NoSuchProof);
                     ^^^^^^^^^^^^ function or associated item cannot be called on `frame_support::pallet_prelude::StorageMap<_GeneratedPrefixForStorageProofs<T>, frame_support::Blake2_128Concat, Vec<u8>, (<T as frame_system::Config>::AccountId, <T as frame_system::Config>::BlockNumber), frame_support::pallet_prelude::ValueQuery>` due to unsatisfied trait bounds

let (owner, _) = Proofs::<T>::get(&proof);
                              ^^^ function or associated item cannot be called on `frame_support::pallet_prelude::StorageMap<_GeneratedPrefixForStorageProofs<T>, frame_support::Blake2_128Concat, Vec<u8>, (<T as frame_system::Config>::AccountId, <T as frame_system::Config>::BlockNumber), frame_support::pallet_prelude::ValueQuery>` due to unsatisfied trait bounds

Proofs::<T>::remove(&proof);
             ^^^^^^ function or associated item cannot be called on `frame_support::pallet_prelude::StorageMap<_GeneratedPrefixForStorageProofs<T>, frame_support::Blake2_128Concat, Vec<u8>, (<T as frame_system::Config>::AccountId, <T as frame_system::Config>::BlockNumber), frame_support::pallet_prelude::ValueQuery>` due to unsatisfied trait bounds

 #[pallet::pallet]
           ^^^^^^ the trait `MaxEncodedLen` is not implemented for `Vec<u8>`

#[pallet::pallet]
          ^^^^^^ the trait `core::default::Default` is not implemented for `<T as frame_system::Config>::AccountId`

#[pallet::storage]
          ^^^^^^^ the trait `core::default::Default` is not implemented for `<T as frame_system::Config>::AccountId`

Can somebody please help me? What should I do next??

1

1 Answer 1

1

Unfortunately there is a bug in the tutorial at the moment. While we work to fix it in the tutorial, here is a fix to the code:

#![cfg_attr(not(feature = "std"), no_std)]

// Re-export pallet items so that they can be accessed from the crate namespace.
pub use pallet::*;

#[frame_support::pallet]
pub mod pallet {
    use frame_support::pallet_prelude::*;
    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 Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
    }

    // 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::event]
    #[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 },
    }

    #[pallet::error]
    pub enum Error<T> {
        /// The claim already exists.
        AlreadyClaimed,
        /// The claim does not exist, so it cannot be revoked.
        NoSuchClaim,
        /// The claim is owned by another account, so caller can't revoke it.
        NotClaimOwner,
    }

    #[pallet::storage]
    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.
    #[pallet::call]
    impl<T: Config> Pallet<T> {
        #[pallet::weight(0)]
        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 });

            Ok(())
        }

        #[pallet::weight(0)]
        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.
            Claims::<T>::remove(&claim);

            // Emit an event that the claim was erased.
            Self::deposit_event(Event::ClaimRevoked { who: sender, claim });
            Ok(())
        }
    }
}

Specifically, we switch the StorageMap from returning a value to returning an Option<Value>. We then handle that in the logic of the code.

Your Answer

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

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