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个),是栈溢出的核心诱因,可通过以下方式优化:
用结构体打包函数参数
为患者信息定义输入结构体,将分散的参数打包传入,减少栈中参数数量: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; } }移除不必要的局部变量
直接操作映射中的结构体,不使用中间局部变量,减少栈占用: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
相关产品推荐
相关产品推荐

