4

I'm a newbie in Rust, Substrate, and blockchain development. I'm developing an ink! smart contract that store a list of items. Since the storage version of Vec is not available yet, I use a Mapping to store the items instead. I've implemented contract methods for adding and getting items successfully. Here is my code:

#[ink(storage)]
#[derive(SpreadAllocate)]
pub struct MyContract {
  map: Mapping<u32, MyStruct>,
}

impl MyContract {
  #[ink(constructor)]
  pub fn default() -> Self {
    ink_lang::utils::initialize_contract(|_| {})
  }

  #[ink(message)]
  pub fn add_item(&mut self, item: MyStruct) {
    self.map.insert(item.id, &item);
  }

  #[ink(message)]
  pub fn get_item(&self, id: u32) -> MyStruct {
    self.map.get(&id).unwrap().clone()
  }
}

Now I'm trying to create a method that returns the whole list to the caller. But I'm not able to find a way to do that. Maybe I should convert Mapping to Vec, but again I can't find a way to do it. Could you please help me? Thanks.

1 Answer 1

7

Mapping is a memory efficient storage type that doesn't hold an index of what's inside it. It is simply a key-value store.

You will need to store a list of keys that contain values inside the Mapping. For example, in our contract we are storing:

    dapps: Mapping<AccountId, Dapp>,
    dapp_accounts: Vec<AccountId>,

When we register a new dapp we store the dapp AccountId to both variables:

            self.dapps.insert(contract, &dapp);
            self.dapp_accounts.push(contract);

We're using ink_prelude::vec::Vec; which is fully loaded into memory. Therefore, it's not appropriate for holding a large amount of values. In future, we will be migrating this to the ink_storage::Vec, which is not currently available.

You need to think about the design of your contract in terms of how you will access the data, as this will determine the amount of gas you use. There are common design techniques from the solidity world that may help to inform you.

1
  • 2
    Maybe to add some extra details here, the Mapping isn't even aware of what elements have been stored using it. It's really just a shim to the storage of the Contracts pallet. See the definition here. So yeah, it doesn't know what's been stored - which is why you'd need something like a memory Vec to keep track of all the keys.
    – HCastano
    Mar 24, 2022 at 0:46

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.