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.

  • 1
    Hi there. A code example would be great to easily understand and help you out – Greg Jeanmart Jan 12 '18 at 9:44
  • @GregJeanmart: I would need to minimize some 2 or 3 contracts, and then paste them here. – goodvibration Jan 12 '18 at 9:48
  • You could post a link to a gist instead of pasting them directly here. – Harry Wright Jan 12 '18 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). – goodvibration Jan 12 '18 at 10:36
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]);
    }
}
  • 1
    Hmmm... replace the struct with a contract... That's interesting; I will give it a try, thank you!!! – goodvibration Jan 12 '18 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? – goodvibration Jan 12 '18 at 11:17
  • Yes that's correct, you will need to write a constructor for a contract. – Harry Wright Jan 12 '18 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? – goodvibration Jan 12 '18 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. – Harry Wright Jan 12 '18 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 :)

  • My array of structures is not dynamic: MyStruct[10][20] private myStructLists. – goodvibration Jan 12 '18 at 9:49
  • Yes, but your structures are too "deep" (plus they are in an array, so it's even deeper :/ ) – Florian Castelain Jan 12 '18 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? – goodvibration Jan 12 '18 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. – Florian Castelain Jan 12 '18 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. – goodvibration Jan 12 '18 at 10:32

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.