-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathRandomizerVRF.sol
More file actions
184 lines (162 loc) · 6.66 KB
/
Copy pathRandomizerVRF.sol
File metadata and controls
184 lines (162 loc) · 6.66 KB
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
// SPDX-License-Identifier: MIT
/**
*
* @title NextGen 6529 - VRF Randomizer Contract
* @custom:date 20-December-2023
* @custom:version 1.9
* @author 6529 team
*/
pragma solidity ^0.8.19;
import "./VRFCoordinatorV2Interface.sol";
import "./VRFConsumerBaseV2.sol";
import "./IStreamLegacyCore.sol";
import "./IStreamAdmins.sol";
import "./StreamPauseDomains.sol";
import "./StreamRandomizerLifecycle.sol";
contract NextGenRandomizerVRF is VRFConsumerBaseV2, StreamRandomizerLifecycle {
event RequestFulfilled(uint256 requestId, uint256[] randomWords);
VRFCoordinatorV2Interface public COORDINATOR;
// chainlink data
uint64 s_subscriptionId;
bytes32 public keyHash = 0x474e34a077df58807dbe9c96d3c009b23b3c6d0cce433e59bbf5b34f823bc56c;
uint32 public callbackGasLimit = 40000;
uint16 public requestConfirmations = 3;
uint32 public numWords = 1;
address gencore;
IStreamLegacyCore public gencoreContract;
IStreamAdmins private adminsContract;
constructor(
uint64 subscriptionId,
address vrfCoordinator,
address _gencore,
address _adminsContract
) VRFConsumerBaseV2(vrfCoordinator) {
COORDINATOR = VRFCoordinatorV2Interface(vrfCoordinator);
s_subscriptionId = subscriptionId;
gencore = _gencore;
gencoreContract = IStreamLegacyCore(_gencore);
adminsContract = IStreamAdmins(_adminsContract);
}
modifier FunctionAdminRequired(bytes4 _selector) {
require(
adminsContract.retrieveFunctionAdmin(msg.sender, address(this), _selector) == true
|| adminsContract.retrieveGlobalAdmin(msg.sender) == true,
"Not allowed"
);
_;
}
function requestRandomWords(uint256 tokenid) public {
require(msg.sender == gencore);
require(
adminsContract.isPaused(StreamPauseDomains.RANDOMNESS_REQUEST) == false,
"Randomness paused"
);
uint256 requestId = COORDINATOR.requestRandomWords(
keyHash, s_subscriptionId, requestConfirmations, callbackGasLimit, numWords
);
uint256 collectionId = tokenIdToCollection[tokenid];
_recordRandomnessRequest(
requestId, collectionId, tokenid, gencoreContract.viewRandomizerEpoch(collectionId)
);
}
function fulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords)
internal
override
{
(uint256 collectionId, uint256 tokenId, bytes32 derivedSeed) =
_fulfillRandomnessRequest(gencoreContract, _requestId, _randomWords);
// The lifecycle marks this request non-pending before the external core
// write, so duplicate callbacks and stale marking fail during any
// reentrant read/write attempt. The catch records only the deterministic
// local post-processing failure outcome.
// slither-disable-start reentrancy-no-eth,reentrancy-events
try gencoreContract.setTokenHash(collectionId, tokenId, derivedSeed) {
if (gencoreContract.isTokenBurned(tokenId)) {
_confirmBurnedTokenRandomnessRecorded(_requestId);
}
_confirmRandomnessFulfillment(_requestId);
emit RequestFulfilled(_requestId, _randomWords);
} catch (bytes memory failureData) {
_markRandomnessPostProcessingFailed(_requestId, failureData);
}
// slither-disable-end reentrancy-no-eth,reentrancy-events
}
// function that calculates the random hash and returns it to the gencore contract
function calculateTokenHash(uint256 _collectionID, uint256 _mintIndex, uint256 _saltfun_o)
public
{
require(msg.sender == gencore);
require(
adminsContract.isPaused(StreamPauseDomains.RANDOMNESS_REQUEST) == false,
"Randomness paused"
);
tokenIdToCollection[_mintIndex] = _collectionID;
requestRandomWords(_mintIndex);
}
function markStaleRequest(uint256 _requestId)
public
FunctionAdminRequired(this.markStaleRequest.selector)
{
_markRandomnessRequestStale(_requestId);
}
function retryRandomnessPostProcessing(uint256 _requestId)
public
FunctionAdminRequired(this.retryRandomnessPostProcessing.selector)
{
(uint256 collectionId, uint256 tokenId, bytes32 derivedSeed, uint256 retryCount) =
_prepareRandomnessPostProcessingRetry(gencoreContract, _requestId);
// Retry reuses the already accepted seed and performs only the
// deterministic core write. The lifecycle state is Fulfilled during the
// external call, so duplicate callbacks and nested retry/stale attempts
// fail closed.
// slither-disable-start reentrancy-no-eth,reentrancy-events
try gencoreContract.setTokenHash(collectionId, tokenId, derivedSeed) {
if (gencoreContract.isTokenBurned(tokenId)) {
_confirmBurnedTokenRandomnessRecorded(_requestId);
}
_confirmRandomnessPostProcessingRetry(_requestId, retryCount);
} catch (bytes memory failureData) {
_markRandomnessPostProcessingRetryFailed(_requestId, failureData, retryCount);
}
// slither-disable-end reentrancy-no-eth,reentrancy-events
}
// function to update callbackGasLimit & keyHash
function updatecallbackGasLimitAndkeyHash(uint32 _callbackGasLimit, bytes32 _keyHash)
public
FunctionAdminRequired(this.updatecallbackGasLimitAndkeyHash.selector)
{
callbackGasLimit = _callbackGasLimit;
keyHash = _keyHash;
}
// function to change the requests other data
function updateAdditionalData(
uint64 _s_subscriptionId,
uint32 _numWords,
uint16 _requestConfirmations
) public FunctionAdminRequired(this.updateAdditionalData.selector) {
s_subscriptionId = _s_subscriptionId;
numWords = _numWords;
requestConfirmations = _requestConfirmations;
}
// function to update contracts
function updateAdminContract(address _newadminsContract)
public
FunctionAdminRequired(this.updateAdminContract.selector)
{
require(
IStreamAdmins(_newadminsContract).isAdminContract() == true, "Contract is not Admin"
);
adminsContract = IStreamAdmins(_newadminsContract);
}
function updateCoreContract(address _gencore)
public
FunctionAdminRequired(this.updateCoreContract.selector)
{
gencore = _gencore;
gencoreContract = IStreamLegacyCore(_gencore);
}
// get randomizer contract status
function isRandomizerContract() external view returns (bool) {
return true;
}
}