-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
VRFV2PlusWrapperConsumerBase.sol
121 lines (110 loc) · 4.96 KB
/
VRFV2PlusWrapperConsumerBase.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol";
import {IVRFV2PlusWrapper} from "./interfaces/IVRFV2PlusWrapper.sol";
/**
*
* @notice Interface for contracts using VRF randomness through the VRF V2 wrapper
* ********************************************************************************
* @dev PURPOSE
*
* @dev Create VRF V2+ requests without the need for subscription management. Rather than creating
* @dev and funding a VRF V2+ subscription, a user can use this wrapper to create one off requests,
* @dev paying up front rather than at fulfillment.
*
* @dev Since the price is determined using the gas price of the request transaction rather than
* @dev the fulfillment transaction, the wrapper charges an additional premium on callback gas
* @dev usage, in addition to some extra overhead costs associated with the VRFV2Wrapper contract.
* *****************************************************************************
* @dev USAGE
*
* @dev Calling contracts must inherit from VRFV2PlusWrapperConsumerBase. The consumer must be funded
* @dev with enough LINK or ether to make the request, otherwise requests will revert. To request randomness,
* @dev call the 'requestRandomWords' function with the desired VRF parameters. This function handles
* @dev paying for the request based on the current pricing.
*
* @dev Consumers must implement the fullfillRandomWords function, which will be called during
* @dev fulfillment with the randomness result.
*/
abstract contract VRFV2PlusWrapperConsumerBase {
error OnlyVRFWrapperCanFulfill(address have, address want);
LinkTokenInterface internal immutable i_linkToken;
IVRFV2PlusWrapper public immutable i_vrfV2PlusWrapper;
/**
* @param _vrfV2PlusWrapper is the address of the VRFV2Wrapper contract
*/
constructor(address _vrfV2PlusWrapper) {
IVRFV2PlusWrapper vrfV2PlusWrapper = IVRFV2PlusWrapper(_vrfV2PlusWrapper);
i_linkToken = LinkTokenInterface(vrfV2PlusWrapper.link());
i_vrfV2PlusWrapper = vrfV2PlusWrapper;
}
/**
* @dev Requests randomness from the VRF V2+ wrapper.
*
* @param _callbackGasLimit is the gas limit that should be used when calling the consumer's
* fulfillRandomWords function.
* @param _requestConfirmations is the number of confirmations to wait before fulfilling the
* request. A higher number of confirmations increases security by reducing the likelihood
* that a chain re-org changes a published randomness outcome.
* @param _numWords is the number of random words to request.
*
* @return requestId is the VRF V2+ request ID of the newly created randomness request.
*/
// solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore
function requestRandomness(
uint32 _callbackGasLimit,
uint16 _requestConfirmations,
uint32 _numWords,
bytes memory extraArgs
) internal returns (uint256 requestId, uint256 reqPrice) {
reqPrice = i_vrfV2PlusWrapper.calculateRequestPrice(_callbackGasLimit, _numWords);
i_linkToken.transferAndCall(
address(i_vrfV2PlusWrapper),
reqPrice,
abi.encode(_callbackGasLimit, _requestConfirmations, _numWords, extraArgs)
);
return (i_vrfV2PlusWrapper.lastRequestId(), reqPrice);
}
// solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore
function requestRandomnessPayInNative(
uint32 _callbackGasLimit,
uint16 _requestConfirmations,
uint32 _numWords,
bytes memory extraArgs
) internal returns (uint256 requestId, uint256 requestPrice) {
requestPrice = i_vrfV2PlusWrapper.calculateRequestPriceNative(_callbackGasLimit, _numWords);
return (
i_vrfV2PlusWrapper.requestRandomWordsInNative{value: requestPrice}(
_callbackGasLimit,
_requestConfirmations,
_numWords,
extraArgs
),
requestPrice
);
}
/**
* @notice fulfillRandomWords handles the VRF V2 wrapper response. The consuming contract must
* @notice implement it.
*
* @param _requestId is the VRF V2 request ID.
* @param _randomWords is the randomness result.
*/
// solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore
function fulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) internal virtual;
function rawFulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) external {
address vrfWrapperAddr = address(i_vrfV2PlusWrapper);
if (msg.sender != vrfWrapperAddr) {
revert OnlyVRFWrapperCanFulfill(msg.sender, vrfWrapperAddr);
}
fulfillRandomWords(_requestId, _randomWords);
}
/// @notice getBalance returns the native balance of the consumer contract
function getBalance() public view returns (uint256) {
return address(this).balance;
}
/// @notice getLinkToken returns the link token contract
function getLinkToken() public view returns (LinkTokenInterface) {
return i_linkToken;
}
}