今天在写完合约在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);
}
}
问题解决~