First of all I am working on Polkadot-v0.9.29. I am struggling to understand the right way to format a pallet call before submitting it as a proposal to the democracy pallet. Let's the pallet call be the famous:

#[pallet::weight(10_000 + T::DbWeight::get().writes(1).ref_time())]
        pub fn do_something(origin: OriginFor<T>, something: u32) -> DispatchResult {

            let who = ensure_signed(origin)?;
            // Update storage.
            // Emit an event.
            Self::deposit_event(Event::SomethingStored { something, who });
            // Return a successful DispatchResultWithPostInfo

consider the following code:

I prepared a function that formats the call as follows:

pub fn create_proposal_hash_and_note(caller: T::AccountId,call:<T as Config>::Call) -> T::Hash {
        let origin = RawOrigin::Signed(caller);
        let call_wrap = Box::new(call);
        let proposal_hash = T::Hashing::hash_of(&call_wrap);
        let proposal_encoded: Vec<u8> = call_wrap.encode();
        match Dem::Pallet::<T>::note_preimage(origin.into(), proposal_encoded){
            Ok(_) => (),
            Err(x) if x == Error::<T>::DuplicatePreimage.into() => (),
            Err(x) => panic!("{:?}", x),

Then I create the formated call, submit the proposal and start a referendum:

let call = Call::<T>::do_something{
//Create and add the proposal
let prop_hash = Self::create_proposal_hash_and_note(virtual_account.clone(),rep_call.into());

I Already checked through testing, that:

  • the referendum is correctly started
  • the proposal hash is registered
  • after voting, the referendum completes normally only problem is the proposal is not enacted. I think it's because the proposal is not correctly formated, but I really don't know Where/why. If you want to see the full code:


Help, please?


Code sample of the test I'm using with the Real pallet call:

let b = match ref_infos{
            pallet_democracy::ReferendumInfo::Finished{approved,end:_} => approved,
            _=> false,
        } ;

        println!("\n\nReferendum status after vote is: {:?}\n present block is: {:?}\n\n",&ref_infos,System::block_number());
        println!("\n\nvote result is:{:?}",b);
        let prop0 = AssetManagement::proposals(0).unwrap().vote_result;
        println!("\n\nVote results:{:?}\n\n",prop0);

        //Proposal enactement should happen 2 blocks later 
            .saturating_add(<Test as crate::Config>::Delay::get()));

//The code line below fails as the pallet call is not executed as it should         
assert_eq!(Roles::RepresentativeLog::<Test>::contains_key(FERDIE), true);   


In the event emitted after the vote, I get the following error message:

Invalid preimage
  • The pallet tests for you linked code work. Which test do you mean is failing? Nov 22, 2022 at 13:08
  • Hello and thanks for looking into it!!you need to un-comment the last line in test.rs. this check should succeed if the call is correctly executed: assert_eq!(Roles::RepresentativeLog::<Test>::contains_key(FERDIE), true); Nov 22, 2022 at 13:39

1 Answer 1


So one of our team member solved this, but it also raised a bunch of other questions that I will add above the various code sections:

  1. I don't understand why the solution won't work without the function below. Even the one who figured it out does not...

    pub fn get_formatted_call(call: <T as Config>::Call) -> <T as Config>::Call {call}

  2. Creating the call, nothing special

         let proposal_call = Call::<T>::representative_approval {
             rep_account: representative.clone(),
             collection: collection_id,
             item: asset_id,
  3. I actually thought that democracy was taking care of the call_dispatch, but I guess we have to do it ourselves...also...why do we need get_formatted_call?? any Rust/Substrate wizard???

let proposal = Box::new(Self::get_formatted_call(proposal_call.into()));

let call = Call::<T>::execute_call_dispatch {
                account_id: virtual_account.clone(),
                proposal: proposal.clone(),
let call_formatted = Self::get_formatted_call(call.into());
let call_dispatch = Box::new(call_formatted);
  1. FINALLY!! after these steps, we can create proposal_hash & proposal_encoded!!!

    let proposal_hash = T::Hashing::hash_of(&call_dispatch);

    let proposal_encoded: Vec<u8> = call_dispatch.encode();

With these I can create a valid preimage, and the proposal is correctly enacted by Democracy pallet. HOWEVER, after spending days reading the democracy pallet tests and benchmarking, this wasn't the solution I was expecting, and I'm pretty confused. If anyone could provide some answers to the questions above...please? Question in the answer....


Forgot to add the content of the call_dispatch function, which HAS TO use Root:

pub fn execute_call_dispatch(origin: OriginFor<T>, account_id: AccountIdOf<T>,  proposal: Box<<T as Config>::Call>) -> DispatchResultWithPostInfo {


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.