1

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.

4
  • 1
    Hi there. A code example would be great to easily understand and help you out Jan 12, 2018 at 9:44
  • @GregJeanmart: I would need to minimize some 2 or 3 contracts, and then paste them here. Jan 12, 2018 at 9:48
  • You could post a link to a gist instead of pasting them directly here. Jan 12, 2018 at 10:26
  • @HarryWright: Thanks, but I've given up the chance of resolving the original (stack-usage) problem via passing a storage structure by reference, since it seems not to be supported in Solidity (well, supported only for internal functions from what I've gathered so far, but I'm doing inter-contract function calls here). Jan 12, 2018 at 10:36

2 Answers 2

1

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]);
    }
}
10
  • 1
    Hmmm... replace the struct with a contract... That's interesting; I will give it a try, thank you!!! Jan 12, 2018 at 11:14
  • P.S.: For a struct, a constructor was "created" for me implicitly. Do I really need to declare it explicitly if I change to a contract? Jan 12, 2018 at 11:17
  • Yes that's correct, you will need to write a constructor for a contract. Jan 12, 2018 at 11:35
  • OK, a few notes to your (working) solution: 1. When I actually makes use of the contract instance which is passed to some given function, I need to use a 'getter' function on the variable that I want to access. For example, suppose that some function takes Person person, and I want to access age, then I need to use person.age(). This might yield some sort of runtime impact, which I now need to investigate. 2. The compiler forces me to change the function modifier from pure to view. Any idea why? Jan 12, 2018 at 11:52
  • 1
    The documentation states that a pure function cannot call any non-pure function. The generated getter function for the other contract is not pure, I think this why you are unable to do this operation. Jan 12, 2018 at 13:32
1

I might not really understand your problem. But from my experience and lot of researches on internet:

  1. 1: Solidity does not handle very well (for developers) dynamicly sized objects (like arrays, strings)
  2. 2: Some types cannot be returned from a contract call

For example, I have a contract making a call to another contract, a few variable types can't be returned this way (but can with an external call, like a web3js call). This include "deep" types, like structures.

Note: This is not an official statement, just some things I got from experience/reading, if someone has an offical documentation, please make an other correct answer :)

6
  • My array of structures is not dynamic: MyStruct[10][20] private myStructLists. Jan 12, 2018 at 9:49
  • Yes, but your structures are too "deep" (plus they are in an array, so it's even deeper :/ ) Jan 12, 2018 at 9:51
  • Your answer leads me to the conclusion that I would need to solve the original problem(Stack too deep, try removing local variables) using a different approach. Any idea besides the obvious which is explicitly mentioned in this error? Jan 12, 2018 at 10:09
  • Not really. I try to simplify and work with the very most "basic" types when I'm coding in solidity, so I avoid structures, arrays and stuff. Jan 12, 2018 at 10:14
  • Doesn't change the bottom line of the problem I'm facing. I can reduce those structures and arrays all you want, but at the bottom line, I have a function which takes something like 9 variables of type uint256, and performs inner function calls, which eventually leads to a stack usage above the permitted limit. Jan 12, 2018 at 10:32

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.