Skip to content

mapping getters don't return structs with arrays correctly #12792

Closed
@ramgos

Description

@ramgos

Whenever there is a mapping from some type to a struct, and the struct contains a dynamic array - calling the getter of the mapping doesn't show the array's values

Compiler version: 0.8.12 (tested also 0.8.7 and 0.8.3)
Target EVM version: london
Framework/IDE: Remix, also reproduced on hardhat ethers
EVM execution environment: javascript VM
Operating system: Linux

example:

pragma solidity ^0.8.0;

contract Contract {
    struct Struct {
        address sender;
        uint256[] numbers;
    }

    mapping(uint256 => Struct) public structs;

    function setValue(uint256 _index, uint256[] memory _array) external {
        structs[_index] = Struct(msg.sender, _array);
    }

    function getStruct(uint256 _index) external view returns(Struct memory) {
        return structs[_index];
    }
}

After setValue(0, [1, 2, 3]), calling getStruct(0) returns both the sender and numbers array, but strcuts(0) returns only the sender
This is also confirmed by the ABI definitions:
structs:

	"inputs": [
		{
			"internalType": "uint256",
			"name": "",
			"type": "uint256"
		}
	],
	"name": "structs",
	"outputs": [
		{
			"internalType": "address",
			"name": "sender",
			"type": "address"
		}
	],
	"stateMutability": "view",
	"type": "function"

getStruct:

			"inputs": [
				{
					"internalType": "uint256",
					"name": "_index",
					"type": "uint256"
				}
			],
			"name": "getStruct",
			"outputs": [
				{
					"components": [
						{
							"internalType": "address",
							"name": "sender",
							"type": "address"
						},
						{
							"internalType": "uint256[]",
							"name": "numbers",
							"type": "uint256[]"
						}
					],
					"internalType": "struct Contract.Struct",
					"name": "",
					"type": "tuple"
				}
			],
			"stateMutability": "view",
			"type": "function"

for the meanwhile, how can I bypass this? I tried calculating the mapping storage slot myself based on the docs, with no success. here is my function:

const keySlot = (mappingSlot, key) => {
    return keccak256(concat([zeroPad(key, 32), mappingSlot]));
};

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions