Created
February 28, 2023 13:32
-
-
Save imqdee/acb25f98f7e5282e53433098c1e9bb32 to your computer and use it in GitHub Desktop.
Easy to implement solutions for the StackTooDeep error
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| pragma solidity >=0.8.19; | |
| contract Test { | |
| // This function raise a "Stack too deep" error | |
| // The explanation for this is due to the constraints of referencing | |
| // variables in the EVM stack. Despite the possibility of having over | |
| // 16 variables in the stack, any attempt to reference a variable beyond slot | |
| // 16 will result in failure. Hence, it can be difficult to identify the exact | |
| // reason for a code's failure, and sometimes making random alterations may appear | |
| // to resolve the issues | |
| function stackTooDeep() external pure returns (uint256) { | |
| uint256 a = 8; | |
| uint256 b = a + 4; | |
| uint256 c = b + 6; | |
| uint256 d = c + 8; | |
| uint256 e = d * 9; | |
| uint256 f = e**2; | |
| uint256 g = a + f; | |
| uint256 h = b * c + g; | |
| uint256 i = 2 * h; | |
| uint256 j = i + 1; | |
| uint256 k = c * a * b + j; | |
| uint256 l = k + 4; | |
| uint256 m = l * l; | |
| uint256 n = m + 1; | |
| uint256 o = n + n * 2; | |
| uint256 p = c + d + o; | |
| return p; | |
| } | |
| // SOLUTION #1 | |
| // Try compiling your contracts using the `--via-ir` flag | |
| // This flag enable more powerful optimization passes that span across functions | |
| // Sometime, it's enough | |
| // SOLUTION #2 | |
| // Use less variables. As simple as that | |
| function fixedUsingLessVariables() external pure returns (uint256) { | |
| uint256 a = 8; | |
| uint256 b = a + 4; | |
| uint256 c = b + 6; | |
| uint256 d = c + 8; | |
| // 'e' is only used in f, meaning we can avoid declaring a variable in that case | |
| // uint256 e = d * 9; | |
| uint256 f = (d * 9)**2; | |
| uint256 g = a + f; | |
| // 'h' is only used by h, which means that we can avoid declaring a variable in this case | |
| // uint256 h = b * c + g; | |
| // 'i' is only used by j, which means that we can avoid declaring a variable in this case | |
| //uint256 i = 2 * (b * c + g); | |
| uint256 j = (2 * (b * c + g)) + 1; | |
| uint256 k = c * a * b + j; | |
| uint256 l = k + 4; | |
| uint256 m = l * l; | |
| uint256 n = m + 1; | |
| uint256 o = n + n * 2; | |
| uint256 p = c + d + o; | |
| return p; | |
| } | |
| // SOLUTION #3 | |
| // you can take advantage of the "block scoping" properties (a la Diamond or Uniswap). | |
| // Split your logic into different blocks | |
| function fixedUsingBlockScope() external pure returns (uint256) { | |
| uint256 result; | |
| { | |
| uint256 a = 8; | |
| uint256 b = a + 4; | |
| uint256 c = b + 6; | |
| uint256 d = c + 8; | |
| uint256 e = d * 9; | |
| uint256 f = e**2; | |
| uint256 g = a + f; | |
| uint256 h = b * c + g; | |
| result = h; | |
| } | |
| { | |
| uint256 i = 2 * result; | |
| uint256 j = i + 1; | |
| uint256 k = j * i + j; | |
| uint256 l = k + 4; | |
| uint256 m = l * l; | |
| uint256 n = m + 1; | |
| uint256 o = n + n * 2; | |
| result = result + 2 + o; | |
| } | |
| return result; | |
| } | |
| // SOLUTION #4 | |
| // The most extreme one. Take advantages of the struct | |
| struct Store { | |
| uint256 a; | |
| uint256 b; | |
| uint256 c; | |
| uint256 d; | |
| uint256 e; | |
| uint256 f; | |
| uint256 g; | |
| uint256 h; | |
| uint256 i; | |
| uint256 j; | |
| uint256 k; | |
| uint256 l; | |
| uint256 m; | |
| uint256 n; | |
| uint256 o; | |
| uint256 p; | |
| } | |
| function fixedUsingStruct() external pure returns (uint256) { | |
| Store memory store = Store(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); | |
| store.a = 8; | |
| store.b = store.a + 4; | |
| store.c = store.b + 6; | |
| store.d = store.c + 8; | |
| store.e = store.d * 9; | |
| store.f = store.e**2; | |
| store.g = store.a + store.f; | |
| store.h = store.b * store.c + store.g; | |
| store.i = 2 * store.h; | |
| store.j = store.i + 1; | |
| store.k = store.c * store.a * store.b + store.j; | |
| store.l = store.k + 4; | |
| store.m = store.l * store.l; | |
| store.n = store.m + 1; | |
| store.o = store.n + store.n * 2; | |
| store.p = store.c + store.d + store.o; | |
| return store.p; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment