0

In my smart contract I've public mapping as mapping (uint=>User) public users where User is a Struct, so is there any way to get the values of this mapping using default getter.

For Example : If we have public uint count then we can simply call it by using Object.count, is it possible with mapping too.

Please help

0

You get a function that takes an index argument. It returns the scalar values in the struct, so everything that isn't itself a mapping or an array.

For instance:

pragma solidity 0.5.1;

contract StuctsGetter {

    struct MyStruct {
        uint a;
        bytes32 b;
        mapping(address => bool) active;
        bytes32[] keys;
    }

    mapping(uint => MyStruct) public myStructs;

    function setMyStruct(uint index, uint a, bytes32 b) public {
        MyStruct storage m = myStructs[index];
        m.a = a;
        m.b = b;
    }

}

You can call instance.myStructs(uint) to fetch the mapped struct at a certain index. It will return a and b but not active or keys.

Avoid a head-scratcher: If there isn't at least one scalar value (i.e. the struct is made entirely of mappings and/or arrays) then the compiler won't know how to construct the "free" getter. It will fail in a confusing way.

To set/get the indexed values in a mapped struct, write your own functions.

function appendKeyToMyStruct(uint _myStruct, address key) public ... {
  myStructs[_myStruct].keys.push(key);
}

function getMyStructKey(uint _myStruct, uint row) public ... {
  return myStructs[_myStruct].keys[row];
}

These patterns may give you some ideas: Are there well-solved and simple storage patterns for Solidity?

A little info about the storage pointer used in the example: https://blog.b9lab.com/storage-pointers-in-solidity-7dcfaa536089

Hope it helps.

  • but what if I want values from all mapped structs and not from certain index – Shubham Naphade Mar 2 at 17:50
  • That would involve enumerating all the mapped structs which is not possible. Mappings don't store the keys. "Mapped Struct with Index" in the link I shared describes a way of coping with this limitation by keeping a list yourself. You'll find lots of Q/A here about iterating mapped values and why it is not possible, like this: ethereum.stackexchange.com/questions/15337/… – Rob Hitchens - B9lab Mar 2 at 18:36
  • I would add that it is seldom necessary to return a complete array, but that's common orientation for devs who are new to the space. A complete justification would take too much space for here, but suffice it to say that gas cost will increase (O(n)) which we do not want, and client software can a) listen to events and b) iterate, therefore c) "return all" would be repetitive and costly in most cases. – Rob Hitchens - B9lab Mar 2 at 18:40
0

First of all, there is no such thing as default setter (mentioned in title of your question).

Now about default getter. Solidity documentation gives the following example:

struct Data {
    uint a;
    bytes3 b;
    mapping (uint => uint) map;
}
mapping (uint => mapping(bool => Data[])) public data;

will generate the following getter:

function data(uint arg1, bool arg2, uint arg3) public returns (uint a, bytes3 b) {
    a = data[arg1][arg2][arg3].a;
    b = data[arg1][arg2][arg3].b;
}

So, default getter returns not the structure, but rather tuple of all atomic structure fields.

In your case getter will look like:

function users (uint id) public returns (/* all atomic fields of User structure */)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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