25.区块时间戳&矿工劫持
2023-06-23 20:46:02 # 00.security

区块时间戳&矿工劫持

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
contract Roulette {
uint public pastBlockTime; // forces one bet per block

constructor() public payable {} // initially fund contract

// fallback function used to make a bet
function () public payable {
require(msg.value == 10 ether); // must send 10 ether to play
require(now != pastBlockTime); // only 1 transaction per block
pastBlockTime = now;
if(now % 15 == 0) { // winner
msg.sender.transfer(this.balance);
}
}
}

这个合约就像一个简单的彩票。每个区块的一笔交易可以押注 10 个以太币,就有机会赢取合约余额。这里的假设是block.timestamp 的最后两位是均匀分布的。如果是这样的话,中奖的几率是十五分之一。

然而,正如我们所知,矿工可以根据需要调整时间戳。在这种特殊情况下,如果合约中有足够的以太池,打包区块的矿工将被可以选择一个时间戳,他可以选择一个符合要求(now % 15 == 0)的时间戳才进行打包自己的交易。通过这样做,他们可能会赢得锁定在该合约中的以太币以及区块奖励。由于每个区块只允许一个人下注,这也很容易受到抢先攻击。

In practice, block timestamps are monotonically increasing and so miners cannot choose arbitrary block timestamps (they must be later than their predecessors). They are also limited to setting block times not too far in the future, as these blocks will likely be rejected by the network (nodes will not validate blocks whose timestamps are in the future).

预防

块时间戳不应该用于熵或生成随机数——即,它们不应该是赢得游戏或改变重要状态的决定因素(直接或通过某种推导)。

有时需要时间敏感的逻辑;例如,用于解锁合同(时间锁定)、几周后完成 ICO 或执行到期日。有时建议使用block.number平均块时间来估计时间;加上出10 second块时间,1 week大约等于60480 blocks. 因此,指定更改合约状态的区块号可能更安全,因为矿工无法轻易操纵区块号。BAT ICO合约采用了这种策略。

如果合约不是特别关心矿工对区块时间戳的操作,这可能是不必要的,但在开发合约时需要注意这一点。

Prev
2023-06-23 20:46:02 # 00.security
Next