I coincidentally bumped into this question. Assuming though that you meant the following:
#[pallet::weight(<T as Config>::WeightInfo::foo(*hint))]
fn foo(hint: u32) -> DispatchResultWithPostInfo {
let real = get_real();
if real > hint {
return <Error<T>>::HintTooLow.with_weight(T::WeightInfo::foo(real);
}
// do something
Ok(Some(T::WeightInfo::foo(real)).into())
}
I would like to explain what will happen and what are the dangers:
When a block author is building a block it goes to its tx pool and finds this tx on top (most priority) and will run its respective weight function => foo(hint)
in your case (to be found in the pallet's weights.rs
). If there is enough weight left in the block, meaning the resulting weight of foo(hint)
(the DispatchInfo
) is less than the available weight left in the block, the block author will include it in the block and validate and apply the extrinsic.
Now the extrinsic's logic will be executed and because your return value is the DispatchResultWithPostInfo
you can give PostDispatchInfo
.
This will be the actual weight that will be accounted for in the block and what the user will pay for in terms of fees. In the other case where an extrinsic has the return value DispatchResult
. The user will pay for the weight determined when authoring the block => DispatchInfo
.
In your case I assume you would like to return the real
weight in any scenario (failing or successfully executing the extrinsic) since otherwise your chain could be spammed. Why?
If for example we would change real
-> hint
:
if real > hint {
return Error<T>::HintTooLow.with_weight(T::WeightInfo::foo(hint));
}
Someone could spam your chain with hint == 0
and not having to pay a dime for the execution and therefore spamming your chain for free.
I still do not understand what you are trying to accomplish or why, but I hope this can be useful for others in the future.
transaction-payment
or write my own payment pallet to take into account theDispatchInfo
&PostDispatchInfo
weights for charging fees.