Passing Storage Structure Addresses Between Solidity Contracts

contract-designsoliditystoragestruct

I have a contract which declares a array of structures allocated in storage.

From this contract, I invoke a function in another contract, which takes a single structure as input.

In order to workaround "syntax obstacles", I pass the contents (variables) of the structure instead.

I needed to add a few more variables to the structure, and now I get the following compilation error:

Stack too deep, try removing local variables.

Instinctively, I believe that the only solution is to pass the structure to the function "by address"

Since I have the array of these structures allocated in storage, I think that it should be feasible.

However, no matter how I try to write it down, I keep getting errors.

When I declare the return-type as address, I get the following compilation error:

Return argument type struct MyStruct storage ref is not implicitly convertible to expected type address.

When I declare the return-type as MyStruct storage, I get the following compilation error:

Location has to be memory for publicly visible functions (remove the "storage" keyword).

When I declare the return-type as MyStruct memory, I get the following runtime error:

Static memory load of more than 32 bytes requested.

Does the Solidity standard state anywhere that this is not feasible?

Thank you.

Best Answer

Instinctively, I believe that the only solution is to pass the structure to the function "by address"

You cannot access the physical addresses of storage variables (like you can with C), this is not allowed in Solidity. The address type is only used to refer to the addresses of other accounts (contract or external), and is not used to refer to memory addresses.

A work around would be to use a smart contract to store your data instead of a struct. This way you would be able to pass the address of the smart contract around instead of having to pass the data around. I've posted an example below:

contract Person {
    uint public age;
    uint public weight;

    function Person(uint _age, uint _weight) public {
        age = _age;
        weight = _weight;
    }
}

contract PersonHolder {

    address[] public people; // Could use Person[] here

    function addPerson(uint age, uint weight) public {
        people.push(new Person(age, weight));
    }

    function getPerson(uint index) public view returns (Person) {
        require(people.length > index);

        return Person(people[index]);
    }
}