我正在编写我的第一个 Eth 合约,我遇到了一个问题,该buy
方法的 gas 消耗(估计)非常高(在出现“超过最大 gas 限额”错误之前快速 > N 百万 gas。)
快速地说,这个想法如下: - 有一张地图(2D 地图),您可以拥有多个区域(这里称为单位,这就是我维护“unitsToState”明显映射的原因)。- 您可以一次购买多个相邻区域,因此创建了一个“块”。- 所以当你购买一个新的区块时,合约必须检查里面的所有单元是否都是空的( unitsToState[x] == 0 )。购买块时,这些状态设置为 1。
我在这里不解释太多细节,因为我猜问题主要是我的“Solidity”糟糕的算法编程。
这个方法可以用代表一个小区域的 fromX、fromY、toX、toY 的 500k gas 来执行,但是当它们彼此相距很远时,我在 gas 估计过程中得到“超出最大 gas 允许”错误。所以真的估计有问题。。
``` ...
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;
}
}
}
...
```