2
// SPDX-License-Identifier: MIT
pragma solidity =0.8.22;

contract A {
    struct User {
        string name;
        uint age;
    }

    mapping(uint => User) public users;

    function getUser(uint id) external view returns (User memory) {
        return users[id];
    }
}

contract B {
    function test() external {
        A a = new A();
        A.User memory user1 = a.getUser(1); // works
        A.User memory user2 = a.users(1); // does not work
    }
}

It seems that the automatically generated getter function users(uint256) is returning tuple(string,uint256) instead of struct User.

I can't find this behavior in the documentation. Is this expected?

2 Answers 2

1

Yes this is expected. A default getter function should return values, not a type.

See the docs for a struct example: https://docs.soliditylang.org/en/latest/contracts.html#getter-functions

1
  • Could you supplement your answer with some specific statements, explaining what the best practice is for my needs? If I'm writing contract A, should I make 'users' a private variable and then implement a getter function myself? If contract A is written by others and I can't control, how should I accurately obtain the struct I need in B?
    – zzh1996
    Nov 7 at 20:13
0

The Solidity docs mention that some struct values are omitted when a default getter returns the struct, for example, a struct that contains arrays or mappings wouldn't return them.

Meaning this struct:

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.9.0;

contract Complex {
    struct Data {
        uint a;
        bytes3 b;
        mapping(uint => uint) map;
        uint[3] c;
        uint[] d;
        bytes e;
    }
    mapping(uint => mapping(bool => Data[])) public data;
}

Would return this:

function data(uint arg1, bool arg2, uint arg3)
    public
    returns (uint a, bytes3 b, bytes memory e)
{
    a = data[arg1][arg2][arg3].a;
    b = data[arg1][arg2][arg3].b;
    e = data[arg1][arg2][arg3].e;
}
3
  • 1
    Could you supplement your answer with some specific statements, explaining what the best practice is for my needs? If I'm writing contract A, should I make 'users' a private variable and then implement a getter function myself? If contract A is written by others and I can't control, how should I accurately obtain the struct I need in B?
    – zzh1996
    Nov 7 at 20:14
  • @zzh1996 I think "Best Practice" relating to this comes down to personal preference and depends on what your specific application is. If you don't mind reading the struct values individually and don't really care about the actual format of the variable/struct, or any of the complex data types that are omitted, then using a default getter likely won't be an issue for you. On the other hand, if you do care about these things, then you probably would want to set your variable's visibility to private and write your own view function to read the data.
    – Rohan Nero
    Nov 7 at 20:53
  • @zzh1996 If you are trying to read the entire struct data from a contract you don't own/didn't create a custom getter for, the only way you can view the struct is to look at the transaction setting the data, or by directly reading the data from the contract's storage.
    – Rohan Nero
    Nov 7 at 21:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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