solidity 生成伪随机数
据说在以太坊上不可能生成真正的随机数,那我们就暂且叫这个是伪随机数吧。
曾经的Fomo3D就因为随机数的问题,被薅了不少羊毛,有兴趣的可以去查一下,我们这个合约规避了Fomo3D的漏洞,但是会引入其它问题,具体以后再谈。
随机数合约
pragma solidity ^0.5.0;
contract Random {
uint256 private _seed = 0;
/* constructor
* */
constructor() public {
}
/* create random number
* */
function random(uint256 seed) public returns(uint256 ret) {
require(msg.sender == tx.origin, "MUST_ORIDINARY_ACCOUNT");
_seed += seed;
ret = uint256(blockhash(block.number - 1));
ret = uint256(keccak256(abi.encodePacked(ret, _seed)));
}
}
要点
require
判断调用者必须是普通账户。- 中间可以添加其它因素或进行多次
keccak256
来生成随机数。我只是觉得太多的计算没什么必要,所以就简单实现了。
部署调用
$ python test_random.py
random number: 0x70f00fce0faf1e32c16344fe2b465bd0cbb3106399d3e736f4e9afcfac431c0a
$ python test_random.py
random number: 0xe77d252064f3b32401942bb2a1c5d1429f4a995a28224ac1f12fa0977d29b32b
$ python test_random.py
random number: 0x4af5d7063e0160656802526c268c70b98e773fe75847a88069e1d0d4617e38ee
可以看到多次调用生成的随机数不一样。
总结
其实在以太坊上生成随机数是个很有意思的问题,欢迎有兴趣的小伙伴联系博主一起讨论研究。