【Solidity】Gas estimation failed-Gas estimation errored with the following message

今天在写完合约在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 failedERROR,根据字面意思看是因为计算不出来所需GAS的费用,即使强制执行transaction也会失败,博主也是小白,推测是GAS开销太大了导致的问题,期待有哪位大佬能出详细的原因解释。

后来博主改变了思路,引入了CET4ListCET6List来存储成绩列表,并使mapping (address=>CET4[]) public addrToCET4mapping (address=>CET6[]) public addrToCET6变为mapping (uint=>address) internal CET4IndexToAddrmapping (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);
    }
}

问题解决~

猜你喜欢

转载自blog.csdn.net/qq_33829547/article/details/80527389
gas