今天在写完合约在remix部署测试的时候遇到了这么一个问题,一旦向合约里写数据就出现如下错误:
Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending?
如下图所示:
网上一直搜索不到解决方法,最后经过自己的一番折腾后,还是解决了!
先说一下想实现的功能,尝试用合约存储四六级成绩,因为可以多次参加考试,所以每个人可以有多次四六级成绩记录。
原先合约代码:
pragma solidity ^0.4.23; import "./Ownable.sol"; contract StudentFactory is Ownable{ struct CET4{ uint32 time; uint32 grade; } struct CET6{ uint32 time; uint32 grade; } mapping (address=>CET4[]) public addrToCET4; mapping (address=>CET6[]) public addrToCET6; mapping (address=>uint) public addrCET4Count; mapping (address=>uint) public addrCET6Count; } contract StudentHelper is StudentFactory{ function addCET4To(address _addr,uint32 _time,uint32 _grade) public onlyOwner{ CET4[] storage CET4List = addrToCET4[_addr]; CET4List[CET4List.length] = CET4(_time,_grade); addrCET4Count[_addr]++; } function addCET6To(address _addr,uint32 _time,uint32 _grade) public onlyOwner{ CET6[] storage CET6List = addrToCET6[_addr]; CET6List[CET6List.length] = CET6(_time,_grade); addrCET6Count[_addr]++; } }
虽然编译没问题,但是一旦调用addCET4To
来写入成绩的时候就会出现Gas estimation failed
的ERROR,根据字面意思看是因为计算不出来所需GAS的费用,即使强制执行transaction也会失败,博主也是小白,推测是GAS开销太大了导致的问题,期待有哪位大佬能出详细的原因解释。
后来博主改变了思路,引入了CET4List
和CET6List
来存储成绩列表,并使mapping (address=>CET4[]) public addrToCET4
和mapping (address=>CET6[]) public addrToCET6
变为mapping (uint=>address) internal CET4IndexToAddr
和mapping (uint=>address) internal CET6IndexToAddr
。
先通过for
循环找出符合地址的CET4[]
和CET6[]
的索引,再用索引去访问数组中具体的成绩。合约代码如下所示:
pragma solidity ^0.4.23; import "./Ownable.sol"; contract StudentFactory is Ownable{ struct CET4{ uint32 time; uint32 grade; } struct CET6{ uint32 time; uint32 grade; } CET4[] CET4List; // 四级成绩列表 CET6[] CET6List; // 六级成绩列表 mapping (uint=>address) internal CET4IndexToAddr; // 四级成绩序号到地址的映射 mapping (uint=>address) internal CET6IndexToAddr; // 六级成绩序号到地址的映射 mapping (address=>uint) public addrCET4Count; mapping (address=>uint) public addrCET6Count; } contract StudentHelper is StudentFactory{ // 给某个地址添加四级成绩记录 function addCET4To(address _addr,uint32 _time,uint32 _grade) public onlyOwner{ uint index = CET4List.push(CET4(_time,_grade))-1; CET4IndexToAddr[index] = _addr; addrCET4Count[_addr]++; } // 给某个地址添加六级成绩记录 function addCET6To(address _addr,uint32 _time,uint32 _grade) public onlyOwner{ uint index = CET6List.push(CET6(_time,_grade))-1; CET6IndexToAddr[index] = _addr; addrCET6Count[_addr]++; } // 获得某个地址的四级成绩 function getCET4ByAddr(address _addr) view public returns (uint32[],uint32[]) { uint32[] memory timeList = new uint32[](addrCET4Count[_addr]); uint32[] memory gradeList = new uint32[](addrCET4Count[_addr]); uint counter = 0; for (uint i = 0; i < CET4List.length; i++) { if(CET4IndexToAddr[i]==_addr){ timeList[counter] = CET4List[i].time; gradeList[counter] = CET4List[i].grade; counter++; } } return(timeList,gradeList); } // 获得某个地址的六级成绩 function getCET6ByAddr(address _addr) view public returns (uint32[],uint32[]) { uint32[] memory timeList = new uint32[](addrCET6Count[_addr]); uint32[] memory gradeList = new uint32[](addrCET6Count[_addr]); uint counter = 0; for (uint i = 0; i < CET6List.length; i++) { if(CET6IndexToAddr[i]==_addr){ timeList[counter] = CET6List[i].time; gradeList[counter] = CET6List[i].grade; counter++; } } return(timeList,gradeList); } }
问题解决~