1

Good day y'all, i'm tying to write a contract which is supposed to interact with another one that has a big struct that i need to retrieve to do some calculation, the struct have 14 properties and it look like this:

mapping(uint256 => Round) public rounds;

struct Round {
    uint256 epoch;
    uint256 startTimestamp;
    uint256 lockTimestamp;
    uint256 closeTimestamp;
    int256 lockPrice;
    int256 closePrice;
    uint256 lockOracleId;
    uint256 closeOracleId;
    uint256 totalAmount;
    uint256 bullAmount;
    uint256 bearAmount;
    uint256 rewardBaseCalAmount;
    uint256 rewardAmount;
    bool oracleCalled;
}

Trying to simply get this struct and return the struct throws stack too deep error:

function getRound(address contractAddress, uint256 epoch) private view returns (Round memory round) {
 (
      ,,,,,
      round.closePrice,
      ,,
      round.totalAmount,
      round.bullAmount,
      round.bearAmount,
      ,
      round.rewardAmount,
      round.oracleCalled
  ) = IContractInterface(contractAddress).rounds(epoch);

I'm not understanding the problem here, i know about the 16 variable limit and i tried to hardcode "contractAddress" and "epoch" to try only retrieving the 14 variables of the struct + 1 variable for the Round struct but still i'm receiving this error

CompilerError: Stack too deep. Try compiling with --via-ir (cli) or the equivalent viaIR: true (standard JSON) while enabling the optimizer. Otherwise, try removing local variables. When compiling inline assembly: Variable dataEnd is 2 slot(s) too deep inside the stack. Stack too deep. Try compiling with --via-ir (cli) or the equivalent viaIR: true (standard JSON) while enabling the optimizer. Otherwise, try removing local variables.

Can you help me out understanding what i'm doing wrong? Thanks!

1
  • medium.com/aventus/… This is a good explanation on this error, and why it might occur even with less than 16 properties in the struct. Commented Aug 7, 2023 at 11:30

1 Answer 1

1

Since you have a mapping, a struct and 14 elements in your struct it is not surprising that you have the stack too deep error.

The EVM callstack can only handle properly the 16/17 elements. For instance the DUP opcode can only duplicate the 16 first elements of the stack while the SWAP opcode can swap from the first through the 17th element.

Possible solutions would be to:

  • lighten your variables in your struct.

  • split your variables in several structs.

  • pack your variables (in your case having 4 epoch times, you could use four uint64 that would result in using only 1 memory slot).

  • Use internal functions to split the input & output.

There are couples of other solutions.

Here are two useful links that will provide you explanation and possible fixes.

https://soliditydeveloper.com/stacktoodeep

https://medium.com/aventus/stack-too-deep-error-in-solidity-5b8861891bae

(this last one was already provided by ChefAharoni in his comment and is an in depth explanation of the error).

2
  • thanks for your comment, the contract isn't mine and i can't make any changes, i can only wrap something around it I read the link that you shared and now it's a little clearer how the stack works though i don't think i can avoid it in this case do you know if i can query the struct, getting back a tuple(14 params), and putting it immediatly inside another struct? somethink like Round memory round; round = IContractInterface(contractAddress).rounds(epoch); This would probably resolve it but i can't do it because of type mismatch between the tucle() and Round @Torof
    – panella87
    Commented Aug 8, 2023 at 10:34
  • Like I said, get the struct and then process it through a function using one of the provided possible solutions.
    – Torof
    Commented Aug 9, 2023 at 0:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.