EVM中循环的成本是多少

写了个排序合约,采用链表的方式保存
不知道到了后期链表越来越长,会不会造成后面的用户进来,交互一次的GAS直接爆炸,因为交互的时候需要循环遍历链表,然后把数据插入到指定的位置
?

请先 登录 后评论

最佳答案 2022-02-04 23:35

遍历链表的 gas随链表长度增长而增长,很容易触及 gas limit 限制。

你可以尝试把找插入位置查找放在链下, 然后在链上验证位置是否正确。

请先 登录 后评论

其它 1 个回答

1312930610

代码如下,我好像已经看到GAS爆炸的一幕了?

//按dna大小排列的链表
    mapping(uint256 => uint256) private mNextStudents;
    //链表的头
    uint256 private constant GUARD = 10000;

    constructor() public {
        mNextStudents[GUARD] = GUARD;
    }

    //prevTokenid.dna大于等于_newDna且_newDna>_nextTokenid.dna
    function _verifyIndex(
        uint256 _prevTokenid,
        uint256 _newDna,
        uint256 _nextTokenid
    ) private view returns (bool) {
        return
            (_prevTokenid == GUARD || mTigers[_prevTokenid].dna >= _newDna) &&
            (_nextTokenid == GUARD || _newDna > mTigers[_nextTokenid].dna);
    }

    //遍历寻找当前插入位置
    function _findIndex(uint256 _newDna) private view returns (uint256) {
        uint256 tokenid = GUARD;
        while (true) {
            if (_verifyIndex(tokenid, _newDna, mNextStudents[tokenid])) {
                return tokenid;
            }
            tokenid = mNextStudents[tokenid];
        }
    }

    //添加NFT链表
    function _addTiger(uint256 _tokenid) private {
        uint256 tokenid = _findIndex(mTigers[_tokenid].dna);
        //指向tokenid原先指向的id
        mNextStudents[_tokenid] = mNextStudents[tokenid];
        //tokenid指向当前ID
        mNextStudents[tokenid] = _tokenid;
    }

    //获取排名
    function _getTop(uint256 _top)
        internal
        view
        virtual
        returns (uint256[] memory _res)
    {
        _res = new uint256[](_top);
        uint256 tokenid = mNextStudents[GUARD];
        for (uint256 i = 0; i < _top; i++) {
            if (tokenid != GUARD) {
                _res[i] = tokenid;
                tokenid = mNextStudents[tokenid];
            } else {
                _res[i] = 999;
            }
        }
    }
请先 登录 后评论
  • 2 关注
  • 0 收藏,2736 浏览
  • 1312930610 提出于 2022-02-04 21:33