Demystifying the “Stack too deep” Error in Solidity: Understanding its Causes and Solutions

Muni V K
CoinsBench
Published in
4 min readJun 30, 2023

--

I am a blockchain developer at Catalyst Technologies Ltd in Canada, where my role involves spearheading the design and development of an innovative web3 carbon registry alongside Pavel Bordioug and our team. This groundbreaking project harnesses the power of blockchain technology to facilitate transparent and efficient trading of carbon credits.

In this post, I aim to share my valuable experience with Solidity and provide insights to the development community, helping them adopt Solidity more effectively.

When working with Solidity, the “Stack too deep” error is a common issue that developers may encounter. This error occurs when the number of local variables, function parameters, and return variables within a function exceeds the maximum stack size limit in the Ethereum Virtual Machine (EVM). The EVM imposes a limit of 16 local variables, including function parameters and return variables.

Let’s consider an example to illustrate this error:

pragma solidity ^0.8.19;

contract Stack2Deep {

function calculate(
uint a1,
uint a2,
uint a3,
uint a4,
uint a5,
uint a6,
uint a7,
uint a8,
uint a9
) public pure returns (uint) {
return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;
}
}

In this example, the `calculate` function takes nine arguments and attempts to calculate their sum. However, when compiling this contract, you would encounter a compilation error due to exceeding the maximum stack size.

**Solutions to Resolve the “Stack too deep” Error**

To overcome the “Stack too deep” error, you can consider implementing the following solutions:

**option 1: Use getter functions**
The easiest approach is to break down the function logic into smaller parts and utilize getter functions to access variables that are not within the stack size limit. By storing some variables as state variables and using getter functions to retrieve their values, you can avoid the “Stack too deep” error.

pragma solidity ^0.8.19;

contract Stack2Deep {
uint a1;
uint a2;

function put(uint x1, uint x2) public {
a1 = x1;
a2 = x2;
}

function get_a1() public view returns (uint) {
return a1;
}

function get_a2() public view returns (uint) {
return a2;
}

function calculate(
uint a3,
uint a4,
uint a5,
uint a6,
uint a7,
uint a8,
uint a9,
uint a10
) public view returns (uint) {
return get_a1() + get_a2() + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10;
}
}

**Option 2: Assign default values**
If some variables have default values, you can assign them directly in the contract, reducing the number of function parameters.

pragma solidity ^0.8.19;

contract Stack2Deep {
uint a1 = 10;
uint a2 = 20;
uint a3 = 30;
uint a4 = 40;
uint a5 = 50;

function calculate(
uint a6,
uint a7,
uint a8,
uint a9,
uint a10
) public view returns (uint) {
return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10;
}
}

**Option 3: Break down the function logic**
You can split the function into multiple functions to distribute the workload across several smaller functions. By dividing the logic, you can reduce the number of variables used within each individual function.

pragma solidity ^0.8.19;

contract Stack2Deep {

function sum(uint x, uint y) public pure returns (uint) {
return x + y;
}

function calculate(
uint a1,
uint a2,
uint a3,
uint a4,
uint a5,
uint a6,
uint a7,
uint a8
) public pure returns (uint) {
return sum(a1, a2) + sum(a3, a4) + sum(a5, a6) + sum(a7, a8);
}
}

**Option 4: Use a struct datatype**
Grouping related variables into a struct can help organize the code and potentially reduce the number of variables used within a function.

pragma solidity ^0.8.19;

contract Stack2Deep {

struct InputData {
uint a1;
uint a2;
uint a3;
uint a4;
uint a5;
}

InputData ip;

function assignInputData(
uint a1,
uint a2,
uint a3,
uint a4,
uint a5
) public {
ip.a1 = a1;
ip.a2 = a2;
ip.a3 = a3;
ip.a4 = a4;
ip.a5 = a5;
}

function calculate(
uint a6,
uint a7,
uint a8,
uint a9,
uint a10
) public view returns (uint) {
return (ip.a1 + ip.a2 + ip.a3 + ip.a4 + ip.a5) + a6 + a7 + a8 + a9 + a10;
}
}

**Option 5: Use fewer variables**
One straightforward solution is to reduce the number of variables used in the function. By refactoring the code to use fewer variables, you can ensure that it stays within the EVM’s stack size limit.

pragma solidity ^0.8.19;

contract Stack2Deep {

function calculate(
uint a1,
uint a2,
uint a3,
uint a4,
uint a5,
uint a6,
uint a7,
uint a8
) public pure returns (uint) {
return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8;
}
}

By applying these solutions, you can overcome the “Stack too deep” error and ensure the successful compilation and execution of your Solidity contract.

--

--

I am a Blockchain developer with 4 years of experience in Solidity smart contract development & active researcher in the field.