You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Solidity医疗合约编译遇Stack too deep错误,求解决方案

解决Solidity合约编译时的"Stack too deep"错误

问题描述

执行Hardhat运行脚本命令$ /mnt/c/Codeeater/node_modules/.bin/hardhat run scripts/major_project.js时,出现编译错误:

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 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.

该错误源于Solidity编译器栈空间不足,主要是合约中部分函数参数过多、局部变量占用栈槽过多导致。

解决方案

方案一:通过Hardhat配置启用IR优化

修改项目根目录下的hardhat.config.js,启用viaIR模式和编译器优化器,让编译器通过中间表示(IR)来优化栈使用:

module.exports = {
  solidity: {
    version: "0.8.19", // 匹配合约pragma声明的版本范围,示例为0.8.19
    settings: {
      optimizer: {
        enabled: true,
        runs: 200, // 优化器运行次数,可根据需求调整
      },
      viaIR: true,
    },
  },
};

配置完成后重新执行编译或运行脚本即可。

方案二:优化合约代码减少栈压力

合约中setDetails、editDetails等函数参数数量过多(最多13个),是栈溢出的核心诱因,可通过以下方式优化:

  1. 用结构体打包函数参数
    为患者信息定义输入结构体,将分散的参数打包传入,减少栈中参数数量:

    contract Record {
        // 新增患者信息输入结构体
        struct PatientInput {
            string ic;
            string name;
            string phone;
            string gender;
            string dob;
            string height;
            string weight;
            string houseaddr;
            string bloodgroup;
            string allergies;
            string medication;
            string emergencyName;
            string emergencyContact;
        }
    
        // 修改setDetails函数
        function setDetails(PatientInput memory input) public {
            require(!isPatient[msg.sender]);
            Patients storage p = patients[msg.sender];
    
            p.ic = input.ic;
            p.name = input.name;
            p.phone = input.phone;
            p.gender = input.gender;
            p.dob = input.dob;
            p.height = input.height;
            p.weight = input.weight;
            p.houseaddr = input.houseaddr;
            p.bloodgroup = input.bloodgroup;
            p.allergies = input.allergies;
            p.medication = input.medication;
            p.emergencyName = input.emergencyName;
            p.emergencyContact = input.emergencyContact;
            p.addr = msg.sender;
            p.date = block.timestamp;
    
            patientList.push(msg.sender);
            isPatient[msg.sender] = true;
            isApproved[msg.sender][msg.sender] = true;
            patientCount++;
        }
    
        // 同理修改editDetails函数
        function editDetails(PatientInput memory input) public {
            require(isPatient[msg.sender]);
            Patients storage p = patients[msg.sender];
    
            p.ic = input.ic;
            p.name = input.name;
            p.phone = input.phone;
            p.gender = input.gender;
            p.dob = input.dob;
            p.height = input.height;
            p.weight = input.weight;
            p.houseaddr = input.houseaddr;
            p.bloodgroup = input.bloodgroup;
            p.allergies = input.allergies;
            p.medication = input.medication;
            p.emergencyName = input.emergencyName;
            p.emergencyContact = input.emergencyContact;
            p.addr = msg.sender;
        }
    }
    
  2. 移除不必要的局部变量
    直接操作映射中的结构体,不使用中间局部变量,减少栈占用:

    function setDetails(...) public {
        require(!isPatient[msg.sender]);
    
        patients[msg.sender].ic = _ic;
        patients[msg.sender].name = _name;
        // ... 依次赋值其他字段
        patients[msg.sender].addr = msg.sender;
        patients[msg.sender].date = block.timestamp;
    
        // ... 其余逻辑代码
    }
    

额外注意

合约中givePermission函数未完成,需补全函数体和返回值定义,否则会引发额外编译错误。


内容的提问来源于stack exchange,提问作者Thamesh chandravanshi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 11:32:02