28

When trying to compile, I am getting the following error:

"Internal compiler error: Stack too deep, try removing local variables."

Is there any way around this? I'm not sure if I'll be able to remove enough variables to fix this.

Thanks!

18

You're hitting a StackTooDeepException.

The Solidity code doesn't appear to be consistent in the number of variables it sees as a problem, but you've got a limit of around 16 or 17. (Though clearly the lower limit of 16 will be the one that kicks in...)

CommonSubexpressionEliminator.cpp and CompilerUtils.cpp:

assertThrow(instructionNum <= 16, StackTooDeepException, "Stack too deep, try removing local variables.");

ContractCompiler.cpp:

solAssert(stackLayout.size() <= 17, "Stack too deep, try removing local variables.");

Without seeing your code it's difficult to comment further on possible solutions, but one thing to try would be to split bigger functions into smaller ones.


Edit 2019:

A very detailed explanation of this error, and how it can be avoided, is discussed in the article “Stack Too Deep”- Error in Solidity.

  • Thanks for the suggestion! Would an array count as 1 local variable? – Amer Ameen Jun 15 '16 at 21:08
  • 3
    I believe so, yes. Otherwise array sizes would also be limited to 16, which isn't a particularly large array. – Richard Horrocks Jun 16 '16 at 8:05
  • I am not trying to revive this, but i had to ask since i am getting this error too. is the maximum number of local variables less than 10 now ? I am having this error with 15 variables – Kaki Master Of Time Feb 20 '18 at 11:19
  • Hi @MedMansour - spotted your other question about this. How many do you have to remove before the error disappears? – Richard Horrocks Feb 20 '18 at 18:45
  • I did get no error when leaving about 8 or 9 variables from my struct, but i already switched to passing a fixed size array instead or sperate arguments. yet i don't know what does local variable means. is it only the variables in arguments ? or the ones in returns() statement or the sum of those with the local variables inside the function. – Kaki Master Of Time Feb 22 '18 at 7:36
4

https://github.com/ethereum/solidity/issues/267

It depends on how complex the expressions inside the function are, but more than 16 local variables will not work. This story should fix it, though: https://www.pivotaltracker.com/n/projects/1189488/stories/99085498

The story has not been started.

  • Seems that it is completed now. – updogliu Dec 12 '17 at 17:54
  • @updogliu or whoever knows the latest news, please do post an answer. – eth Dec 30 '17 at 13:00
  • I tend to agree with @eth. This doesn't seem to be resolved on 0.4.18. – goodvibration Jan 12 '18 at 10:13
4

A workaround for this is to put local variables into an array of the same type as on the EVM arrays only occupy one stack slot. Thereby, functions can get much bigger before hitting the limit of 16 slots.

For example:

contract A {

    // This will get the error: 'stack too deep, try...'
    function deepStack
    (
        uint8 _a,
        uint8 _b,
        uint8 _c,
        uint8 _d,
        uint16 _e,
        uint16 _f,
        uint16 _g,
        uint16 _h,
        uint32 _i,
        uint32 _j,
        uint32 _k,
        uint32 _l,
        uint64 _m,
        uint64 _n,
        uint64 _o,
        uint64 _p,
        uint128 _q
    )
        public
        returns (bool success)
    {
        return true;
    }

    // This function works
    function deepStackSolution
    (
        uint8[] _aToD,
        uint16[] _eToH,
        uint32[] _iToL,
        uint64[] _mToP,
        uint128 _q
    )
        public
        returns (bool success)
    {
        return true;
    }

}

However, keep in mind that the storage capability of each slot is still limited. This way the provided storage will just be used more efficiently. If you are using really large numbers this might soon reach it's limits as well.

0

Here's a funny thing. I simply changed a method from public to external and got the message:

/Users/cliff/Documents/in-app-pro-shop/contracts/SKUFactory.sol:42:23: 
CompilerError: Stack too deep, try removing local variables.
skus.push(SKU(_shopId, skuId, _skuTypeId, _price, _name, _desc, _consumable, _limited, _limit));
              ^-----^

Changing it back to public removes the error! Apparently, it's a little more nuanced than just how many local variables there are. Here's the function:

/**
 * @notice Create a SKU (Shopkeeping Unit) for a Shop
 * @dev Can only be run by shop owner
 */
function createSKU(
    uint256 _shopId,
    uint256 _skuTypeId,
    uint256 _price,
    string _name,
    string _desc,
    bool _consumable,
    bool _limited,
    uint256 _limit
)
    public
    onlyShopOwner(_shopId)
    returns(uint256)
{
    // SKUs must have a non-zero price
    require(_price > 0);

    // Get SKU ID
    uint256 skuId = skus.length;

    // Create and store SKU Type
    skus.push(SKU(_shopId, skuId, _skuTypeId, _price, _name, _desc, _consumable, _limited, _limit));

    // Add SKU to Shop's SKU list
    shopSKUs[_shopId].push(skuId);

    // Add SKU ID to SKU Type's SKU list
    skuTypeSKUs[_skuTypeId].push(skuId);

    // Emit Event with name of the new SKU
    emit NewSKU(_shopId, skuId, _name);

    // Return the new SKU ID
    return skuId;
}

I was making the change in response to this discussion about best practices for external vs public, where it is explained (albeit, sort of murkily) how functions are handled differently in those cases. I'm guessing that's at the root of why there isn't a specific number of local variables that triggers this error.

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.