太多的气体消耗



我正在编程我的第一份ETH合同,我正在面临问题,buy方法的气体消耗(估计)确实很高(快速> n百万美元之前获得"最大气体津贴超过"错误"。)

快速,这个想法是以下内容:

  • 有一个带有多个区域的地图(2D地图)(在这里称为单位,这就是为什么我要维护" unitstostate"显而易见的映射)。
  • 您可以一次购买多个相邻区域,因此"块"是创建的。
  • 因此,当您购买新块时,合同必须检查内部的所有单元是否为空(unitstostate [x] == 0)。购买块时,将这些状态设置为1。

我在这里没有解释太多细节,因为我猜问题主要是"坚固性"。我的不良算法编程。

该方法可以使用frofx,fromy,fromy,tox,代表一个小区域的ARROUND 500K气体执行,但是当这些区域彼此远离时,我得到了"最大气体津贴"。在我的气体估计期间的错误..所以我真的想有问题。

    ...
    struct Block {
        address owner;
        uint fromX;
        uint fromY;
        uint toX;
        uint toY;
        string imageUrl;
        string redirectUrl;
        string text;
        bool removed;
    }   
    
    uint size = 100;
    mapping (uint => uint) unitsToState;
    Block[] public blocks;
    uint public areaPrice;
    uint public areaPerUnit;
    ...

    function buy(uint fromX, uint fromY, uint toX, uint toY, string imageUrl, string redirectUrl, string text) payable public {
        require(fromX >= 0);
        require(fromY >= 0);
        require(fromX <= toX);
        require(fromY <= toY);
        require(toX < size);
        require(toY < size);
        
        // Here do check of collisions.
        for (uint i = fromX; i <= toX; i++) {
            for (uint j = fromY; j <= toY; j++) {
                require(getUnitsToState(i*size*size + j) == 0);
            }    
        }
        
        uint width = toX - fromX + 1;
        uint height = toY - fromY + 1;
        uint areaCount = width * height * areaPerUnit;
        uint price = areaCount * areaPrice;
        require(msg.value >= price);
        
        Block memory b = Block(
           msg.sender,
           fromX,
           fromY,
           toX,
           toY,
           imageUrl,
           redirectUrl,
           text,
           false
        );
        blocks.push(b);
        
        // Registrer units states.
        for (i = fromX; i <= toX; i++) {
            for (j = fromY; j <= toY; j++) {
                unitsToState[i*size*size + j] = 1;
            }    
        }
    }
    ...

大循环,尤其是在嵌套环的情况下,坚固性很危险。您必须小心在每次迭代中执行的逻辑。

在您的情况下,这是您设置unitsToState标志的第二个循环,该标志会导致气体使用情况巨大。每次存储非零数据的呼叫的费用为20,000天气(零为5,000)。您正在招致循环的每一个迭代。

看来,您需要在Block结构内进行碰撞检查所需的一切。您可以使用它吗?

for (uint8 i = 0; i < blocks.length; i++) {
  Block storage bTest = blocks[i];
  bool xIntersect = int(fromX) - int(bTest.toX) <= 0 && int(toX) - int(bTest.fromX) >= 0;
  bool yIntersect = int(fromY) - int(bTest.toY) <= 0 && int(toY) - int(bTest.fromY) >= 0;
  require (!(xIntersect && yIntersect));
}

请参阅黄皮纸的附录G。

最新更新