Remix: CompilerError: Stack too deep when compiling inline assembly: Variable value0 is 1 slot(s) too deep inside the stack.
   2 分钟阅读    朱安邦

问题描述

在 Remix 0.6.12 版本上报错:

CompilerError: Stack too deep when compiling inline assembly:
Variable value0 is 1 slot(s) too deep inside the stack.

在 Remix 0.8.17 版本上报错

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 value0 is 1 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.

测试的合约代码

// SPDX-License-Identifier: GPL-3.0
// pragma solidity 0.6.12;
pragma solidity 0.8.17;
pragma experimental ABIEncoderV2;


contract Demo {
    struct UserInfo {
        // 账单属性
        bool isLocked; // 是否为锁定账单
        uint256 billType; // 账单类型的ID(Actived Bill 的type永远为 0)
        // 核心
        uint256 amount; // 用户在池子内的最新余额
        uint256 flyRewardDebt; // 用户已经收到的 FLY  奖励数量
        uint256 fiboRewardDebt; // 用户已经收到的 FIBO 奖励数量
        uint256 lockStartTime; // Locked Bill: 开始时间戳
        uint256 lockEndTime; // Locked Bill: 结束时间戳
        // 用户历史账单相关的信息:供前端显示
        uint256 historyBillId; // 当前的账单ID
        uint256 timestamp; // block.timestamp
        bool isDeposit; // 是否为取款
        address lpToken; // LP Token 地址
        uint256 pId; // LP Token Pool Id
        uint256 singleAmount; // 最新一次操作金额
    }
    mapping(address => UserInfo[]) public userHistoryBill;
}

问题的原因

数据结构 mapping(address => UserInfo[]) public userHistoryBill;,此时只需要把 UserInfo 内的数量,减少到不超过 12 个就可以。

上面 UserInfo 内有 13 个元素。我们去掉一个,比如把 bool isLocked; // 是否为锁定账单注释掉。此时就不会报错了。

正确的代码演示

// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.6.12;
// pragma solidity 0.8.17;
pragma experimental ABIEncoderV2;

contract Demo {
    struct UserInfo {
        // 账单属性
        // bool isLocked; // 是否为锁定账单 ✅ struct 内不超过12个元素即可
        uint256 billType; // 账单类型的ID(Actived Bill 的type永远为 0)
        // 核心
        uint256 amount; // 用户在池子内的最新余额
        uint256 flyRewardDebt; // 用户已经收到的 FLY  奖励数量
        uint256 fiboRewardDebt; // 用户已经收到的 FIBO 奖励数量
        uint256 lockStartTime; // Locked Bill: 开始时间戳
        uint256 lockEndTime; // Locked Bill: 结束时间戳
        // 用户历史账单相关的信息:供前端显示
        uint256 historyBillId; // 当前的账单ID
        uint256 timestamp; // block.timestamp
        bool isDeposit; // 是否为取款
        address lpToken; // LP Token 地址
        uint256 pId; // LP Token Pool Id
        uint256 singleAmount; // 最新一次操作金额
    }
    mapping(address => UserInfo[]) public userHistoryBill;
}

问题备注

⚠️ 注意:这是 Remix 的问题,如果我们使用类似 Hardhat 脚手架,编译和部署的时候不会收到此警告。

关于站长

我叫朱安邦,本站的站长。如果您对网站有什么好的建议,欢迎在 Twitter 上与我交流