5

I have a contract that's doing a fairly complex calculation with some intermediate calculations, and I'm running into the "stack too deep" problem.

I've tried to use a memory array within the function to save temporary "local variables" instead of creating new local variables.

For example, instead of:

function usingLocalVars() {
  // Get 3 uint values from a getter function call from another contract
  // and save as local variables uint a, uint b, uint c:
  var(a, b, c) = otherContract.getter(param);

  // Perform some computation an a, b, and c and save as another variable d
  uint d = someOperation(a, b, c);

  /** other code with a return **/

}

Re-written using memory array:

function usingMemoryArray() {
  // Get 3 uint values from a getter function call from another contract
  // and store into memory array temp:

  // create memory array
  uint[4] memory temp;

  // save values into memory array
  (temp[0], temp[1], temp[2]) = otherContract.getter(param);

  // Perform some computation an a, b, and c and save into temp[3]
  temp[3] = someOperation(temp[0], temp[1], temp[2]);

  /** other code with a return **/
}

So what I've tried to do:

  1. Eliminate almost all local variables by doing the above (memory array)
  2. Removed all named return variables, i.e. returns (uint x, uint y, uint z) => returns (uint, uint, uint)

Current function summary:

  • 1x function input paramater
  • memory array of length 17 (all my "temp" variables)
  • 1x int local variable
  • The function does call some other methods within the contract (such as someOperation()) above. Would this potentially be another cause of this problem? Needing to limit the local var used in other method calls (e.g. someOperation())?

Does using a memory array as I mentioned above actually help for this problem (stack too deep)?

5
  • Are any of the function calls recursive? I believe that in the EVM, that error message can come from the traditional "your call stack is too deep" sort of issues as well as pushing too many values onto the stack. You seem to have tackled only the latter.
    – user19510
    Jan 19, 2018 at 22:59
  • Thanks. None of the function calls are recursive and there is no looping. Basically function calls are just getters as well as pure functions.
    – carlolm
    Jan 19, 2018 at 23:10
  • Interesting. Any chance you can share your code so I can try to reproduce the issue?
    – user19510
    Jan 19, 2018 at 23:11
  • 1
    I'm having too much trouble trying to get your tests to run. :-) Have you tried removing various pieces of the function? E.g., remove the event logging and see if things work then? (The event takes quite a few parameters.)
    – user19510
    Jan 19, 2018 at 23:31
  • Thanks for trying! Yes, there is a lot going on in the code. OK it seems like my memory array assignment: (temp[0]...) = getter() is limited to 8 elements, where I originally had 9. Isolating that, works with 8 (at least that bit of code), fails with 9, so will see if adjusting with that resolves it.
    – carlolm
    Jan 19, 2018 at 23:44

2 Answers 2

3

So my temp variable assignments were causing the problem. It works if limiting to 8 assignments at a time:

This fails (9 variable assignments):

(temp[0], temp[1], temp[2], temp[3], temp[4], temp[5], temp[6], temp[7], temp[8]) = (1, 2, 3, 4, 5, 6, 7, 8, 9);

But this works (8 assignments at a time):

(temp[0], temp[1], temp[2], temp[3], temp[4], temp[5], temp[6], temp[7]) = (1, 2, 3, 4, 5, 6, 7, 8);
(temp[8], temp[9], temp[10], temp[11], temp[12], temp[13], temp[14], temp[15]) = (9, 10, 11, 12, 13, 14, 15, 16);

And also, using the memory array does avoid the stack too deep problem of local variables.

2

Maybe you've tried this but some debugging in Remix with empty getter() and someOperation() functions that just return values shows the max stack depth reaches 12 items when I use the first method but only 9 for the second. I'm yet to fully understand the differences but consider using remix and checking the debug screen to help if you haven't already.

enter image description here

1
  • Thanks, that's a great suggestion. I do use remix but I hadn't checked that yet.
    – carlolm
    Jan 20, 2018 at 0:18

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.