@@ -47,13 +47,16 @@ contract NexoraOracle is VRFConsumerBaseV2Plus {
4747
4848 // L2 Sequencer Parameters
4949 AggregatorV2V3Interface public immutable sequencerUptimeFeed;
50- uint256 public GRACE_PERIOD_TIME = 3600 ;
50+ uint256 public GRACE_PERIOD_TIME = 3600 ;
5151 uint256 public SEQUENCER_FEED_HEARTBEAT = 86400 ; //q Is this correct
5252 bool public immutable isL2;
5353
5454 //Validation parameters
55+ uint256 public lastValidationTime;
56+ uint256 public validationInterval = 3600 ; //1 hour default
5557 uint256 public validationThreshold;
5658 uint256 randomSamplingWindow;
59+ // uint256 public validationInterval= 3600; //1 hour default
5760 mapping (uint256 => uint256 ) requestIdToTimestamp;
5861 mapping (uint256 => address []) requestIdToAssets; //Tracks which assets are being validated
5962 mapping (uint256 => mapping (address => uint256 )) requestIdToAssetPrice; //Store prices for validation
@@ -140,6 +143,30 @@ contract NexoraOracle is VRFConsumerBaseV2Plus {
140143 priceFeed: AggregatorV3Interface (_priceFeed),
141144 decimals: decimals
142145 });
146+
147+ assetList.push (_assetAddress);
148+ }
149+
150+ function updateAssetPrice (address assetAddr ) external {
151+ require (! assets[assetAddr].isDeprecated, "Asset is deprecated " );
152+
153+ // //If asset has a pending validation,wait for it
154+ if (assets[assetAddr].lastRequestId != 0 ) {
155+ return ;
156+ }
157+
158+ // // Get current price
159+ uint256 currentPrice = _getValidatedPrice (address (assets[assetAddr].priceFeed), assets[assetAddr].decimals);
160+
161+ // If price isn't within the deviation range validation will be triggered
162+ if (! isPriceWithinDeviation (currentPrice, assets[assetAddr].price)) {
163+ // Trigger validation for this asset
164+ address [] memory singleAsset = new address [](1 );
165+ singleAsset[0 ] = assetAddr;
166+ _requestRandomValidation (singleAsset);
167+ } else {
168+ _updateAssetPrice (assetAddr, currentPrice);
169+ }
143170 }
144171
145172 function calculateEMAPrice (address assetAddr ) public view returns (uint256 ) {
@@ -168,6 +195,37 @@ contract NexoraOracle is VRFConsumerBaseV2Plus {
168195 return uint256 (exp (decayTime).unwrap ());
169196 }
170197
198+ // Meant to be called by validators/users to trigger priceValidation on a constant basis, can be automated..
199+ function requestPriceValidation () external {
200+ require (block .timestamp >= lastValidationTime + validationInterval, "Too soon for validation " );
201+ require (assetList.length > 0 , "No assets to validate " );
202+
203+ address [] memory assetsToValidate = new address [](assetList.length );
204+ uint256 validAssetCount = 0 ;
205+
206+ for (uint256 index = 0 ; index < assetList.length ; index++ ) {
207+ if (! assets[assetList[index]].isDeprecated) {
208+ assetsToValidate[validAssetCount] = assetList[index];
209+ validAssetCount++ ;
210+ }
211+ }
212+
213+ address [] memory finalAssets = new address [](validAssetCount);
214+ for (uint256 index = 0 ; index < validAssetCount; index++ ) {
215+ finalAssets[index] = assetsToValidate[index];
216+ }
217+
218+ if (finalAssets.length > 0 ) {
219+ _requestRandomValidation (finalAssets);
220+ lastValidationTime = block .timestamp ;
221+ }
222+ }
223+
224+ // //Called by the vrf (callback) when random price validation is requested..
225+ // function fulfillRandomWords(uint256 requestId, uint256[] calldata randomWords) external virtual {
226+ // _fulfillRandomWords(requestId, randomWords);
227+ // }
228+
171229 function _requestRandomValidation (address [] memory assetsToValidate ) internal {
172230 // Storing the current prices
173231 uint256 requestId = s_vrfCoordinator.requestRandomWords (
@@ -239,8 +297,7 @@ contract NexoraOracle is VRFConsumerBaseV2Plus {
239297 emit SequencerStatusChecked (isSequencerUp, timeSinceUp);
240298 }
241299
242- //It's called by the vrf
243- function fulfillRandomWords (uint256 requestId , uint256 [] calldata randomWords ) external virtual override {
300+ function fulfillRandomWords (uint256 requestId , uint256 [] calldata randomWords ) internal virtual {
244301 if (randomWords.length == 0 ) {
245302 revert InvalidRandomness ();
246303 }
@@ -293,6 +350,7 @@ contract NexoraOracle is VRFConsumerBaseV2Plus {
293350 return deviation <= maxPriceDeviation;
294351 }
295352
353+ //INTERNAL FUNCTIONS
296354 function _updateAssetPrice (address assetAddr , uint256 newPrice ) internal {
297355 Asset storage asset = assets[assetAddr];
298356
@@ -327,12 +385,6 @@ contract NexoraOracle is VRFConsumerBaseV2Plus {
327385
328386 // Determines whether to perform the validation or not
329387 function _shouldValidateBasedOnRandomness (uint256 randomValue , uint256 requestTime ) internal view returns (bool ) {
330- // To check if the timeElapsed surpasses the sampling window
331- uint256 timeElapsed = block .timestamp - requestTime;
332- if (timeElapsed > randomSamplingWindow) {
333- return false ;
334- }
335-
336388 return (randomValue % 100 ) < validationThreshold;
337389 }
338390
@@ -388,4 +440,8 @@ contract NexoraOracle is VRFConsumerBaseV2Plus {
388440 function setSequencerHeartbeat (uint256 _hearbeat ) external onlyOwner {
389441 SEQUENCER_FEED_HEARTBEAT = _hearbeat;
390442 }
443+
444+ function setValidationInterval (uint256 _interval ) external onlyOwner {
445+ validationInterval = _interval;
446+ }
391447}
0 commit comments