3

I want to write a function which a user can call with an asset id and the amount of which it wants to deposit. I need to check if said asset id is within a list of allowable assets, which can change over time.

Something like this

pub fn add_margin(
    origin: OriginFor<T>,
    asset: AssetIdOf<T>,
    amount: T::Balance,
) -> DispatchResult {
    let acc = ensure_signed(origin)?;
    SupportedAssets<T>::contains(asset)?;
    // do stuff ...

I've checked the frame_support::storage::types docs and couldn't find a storage type that directly implements what I'm looking for.

I've thought of two alternatives:

  1. Using a StorageValue with aHashSet in it, getting the set and checking if it contains the asset id
  2. Using a StorageMap which maps asset id to the unit type, thus checking if it contains the asset id as key and ignoring the stored value.

Any recommendations?

2
  • Can you elaborate your scenario and/or provide some code you want to work?
    – Shawn Tabrizi
    Mar 9, 2022 at 18:51
  • I tried to elaborate more by adding a code snippet and elaborating on the alternatives
    – Angelo
    Mar 9, 2022 at 19:17

1 Answer 1

2

I think for this specific scenario, something like a StorageMap to the unit type makes sense.

But... it really depends more on your overall usage scenario. Simplifying, your concerns should be, in order:

  1. Reducing the number of storage reads.
  2. Reducing the size of the storage read. (Also, ensuring your storage is bounded.)

So imagine the scenario you use a bounded vector. That means it will only take 1 read to get all of the supported assets, but the read will be a larger encoded value than just a single asset, but also this storage item would need to be bounded in size, so you could not support an unlimited number of whitelisted assets in this object.

Now imagine you have a StorageMap. Reading if one asset is supported will be as efficient as you can get with a storage read, but then you could never really write code where you list all of the supported assets, since that would be one storage read each, and you will quickly run out of weight.

Imagine you use both a bounded vec and a storage map, so that you can have both options to you, but now your overall blockchain storage will be doubled(-ish).

Finally, you can imagine not using storage at all, and hard-coding a table of accepted assets into the Runtime itself as some configurable value. This is of course most efficient, and you can do pretty much unlimited stuff here, but then you would need to update your runtime every time you want to update this hard-coded list.

So there is no right answer. It really depends on the overall usage pattern you are driving.

1
  • Fantastic. I agree there doesn't seem to be a perfect solution, but thanks to your answer and can think about what I should prioritize.
    – Angelo
    Mar 9, 2022 at 20:17

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.