mkdir vrf; cd vrf
truffle init
npm install @chainlink/contracts --save
pragma solidity 0.6.2;
import "@chainlink/contracts/src/v0.6/VRFConsumerBase.sol";
abstract contract VRFConsumerBase is VRFRequestIDBase {
...
function fulfillRandomness(bytes32 requestId, uint256 randomness)
external virtual;
function requestRandomness(bytes32 _keyHash, uint256 _fee, uint256 _seed)
public returns (bytes32 requestId)
{
...
}
...
}
上面列出了 VRFConsumerBase 合约的两个基本方法,一个是 requestRandomness 方法,它是用来发起一个 VRF 请求的方法,在调用的时候呢,需要传入三个参数:
· _keyHash: 节点的公钥哈希。因为随机数及其证明的生成,是通过椭圆曲线密码学来完成的,所以需要一对公钥和私钥。公钥是节点公开的密钥,目前可用的 VRF 节点公钥及 VRF 节点的其他相关信息,可用在 Chainlink 官方文档上查到。
· _fee: 用户发起一次 VRF 请求所需要花费的费用,这个费用也可以在节点公布的相关信息中查阅到。如果费用没有达到节点的最低要求,那么 VRF 请求无法完成。费用是以 LINK token 形式支付,所以用户合约需要持有足够的 LINK token。
· _seed: 用户提供的种子,用于生成随机数。用户需要给出高质量的种子。这里我们需要解释一下 VRF 的特点,VRF 是通过种子与节点私钥做椭圆曲线中的计算得来的,同一个种子对应的随机数也是相同的,所以用户需要每次都给出不一样的且不可预测的种子。这很重要。因为任何可以左右用户种子的因素,都可以与链下的节点勾结作恶,生成他们想要的随机数,从而损害用户的利益。区块链中,我们很容易就找到这么一个随机源就是区块哈希,但是区块哈希是可以被矿工控制的(虽然很难),所以建议不能仅使用区块链哈希,还需要与其他随机源一起使用生成种子。比如下面就是一个例子。
function makeRequest(uint256 userProvidedSeed)
public returns (bytes32 requestId)
{
uint256 seed = uint256(keccak256(abi.encode(userProvidedSeed, blockhash(block.number)))); // Hash user seed and block hash
return requestRandomness(keyHash, fee, seed);
}
constructor(address _vrfCoordinator, address _link) public {
vrfCoordinator = _vrfCoordinator;
LINK = LinkTokenInterface(_link);
}
constructor(address _vrfCoordinator, address _link)
VRFConsumerBase(_vrfCoordinator, _link) public {
// 其他一些初始化参数
}
bytes32 internal constant keyHash = 0xced103054e349b8dfb51352f0f8fa9b5d20dde3d06f9f43cb2b85bc64b238205;
uint256 internal constant fee = 10 ** 18;
function getRandomness(uint256 userProvidedSeed)
public returns (bytes32 requestId) {
require(LINK.balanceOf(address(this)) > fee, "Not enough LINK - fill contract with faucet");
uint256 seed = uint256(keccak256(abi.encode(userProvidedSeed, blockhash(block.number)))); // Hash user seed and blockhash
bytes32 _requestId = requestRandomness(keyHash, fee, seed);
return _requestId;
}
在这个请求函数中,我们把用户合约和区块哈希共同作为种子。keyHash 和 fee 就作为常量直接写在合约里,也可以写到 setter 方法中或者构造函数中。
接下来就是复写接收方法。
uint256 public random;
function fulfillRandomness(bytes32 requestId, uint256 randomness)
external override {
random = randomness.mod(100).add(1);
}
pragma solidity 0.6.2;
import "@chainlink/contracts/src/v0.6/VRFConsumerBase.sol";
// import this if you are using remix
// import "https://raw.githubusercontent.com/smartcontractkit/chainlink/develop/evm-contracts/src/v0.6/VRFConsumerBase.sol";
contract MyVRFContract is VRFConsumerBase {
constructor(address _vrfCoordinator, address _link)
VRFConsumerBase(_vrfCoordinator, _link) public {
}
bytes32 internal constant keyHash = 0xced103054e349b8dfb51352f0f8fa9b5d20dde3d06f9f43cb2b85bc64b238205;
uint256 internal constant fee = 10 ** 18;
function getRandomness(uint256 userProvidedSeed) public returns (bytes32 requestId) {
require(LINK.balanceOf(address(this)) > fee, "Not enough LINK - fill contract with faucet");
uint256 seed = uint256(keccak256(abi.encode(userProvidedSeed, blockhash(block.number))));
bytes32 _requestId = requestRandomness(keyHash, fee, seed);
return _requestId;
}
uint256 public random;
function fulfillRandomness(bytes32 requestId, uint256 randomness) external override {
random = randomness.mod(100).add(1);
}
}
版权声明:项目均采集于互联网, 空投币 无法审核全面,且希望大家能赚钱,请谨慎切勿上当受骗!
温馨提示:★★★天上真会掉馅饼!天道酬勤,都是机会!不错过每个空投糖果!真假难以辨认,尽量0撸!