我正在编程我的第一份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。