Same validation is being executed in Keeper and VRF
In Keeper.sol there is a performUpkeep function,
which makes a call to requestVRF function that is in VRF.sol .
Both of these functions perform the same check, which can be seen in performUpkeep on lines 34 - 40, and in requestVRF on lines 102 - 107.
There is no need to perform these checks in both of the functions, because of their dependence on each other. If requestVRF fails, performUpkeep fails too.
function performUpkeep ( bytes calldata performData) external override {
uint256 canvasId = abi. decode( performData, ( uint256 ));
Schema. VRFHelper memory info = ICanvas( canvasAddress). getVRFHelper( canvasId);
if (
! info. vrfPending &&
info. tokenIdCounter - info. randomizedTraitsCounter > 0 &&
info. vrfLastRunTimestamp + ( info. vrfMinuteInterval * 60 ) < block.timestamp
) {
CanvasVRF( vrfAddress). requestVRF( canvasId);
}
}
function requestVRF ( uint256 canvasId ) external {
Schema. VRFHelper memory info = ICanvas( canvasAddress). getVRFHelper( canvasId);
if ( info. vrfPending ||
info. tokenIdCounter - info. randomizedTraitsCounter == 0 ||
info. vrfLastRunTimestamp + ( info. vrfMinuteInterval * 60 ) > block.timestamp )
revert VRFNotNeeded();
uint256 requestId = vrfCoordinator. requestRandomWords( keyHash, canvasIdToSubscriptionId[ canvasId], 7 , 300000 , 1 );
vrfToCanvasId[ requestId] = canvasId;
ICanvas( canvasAddress). setVrfResult( canvasId, 0 , "requested" );
}
Recommendation
Remove the validation from performUpkeep function and just execute the call to requestVRF.
function performUpkeep ( bytes calldata performData) external override {
uint256 canvasId = abi. decode( performData, ( uint256 ));
CanvasVRF( vrfAddress). requestVRF( canvasId);
}
Or if you do not want performUpkeep to revert you can do it like this:
function performUpkeep ( bytes calldata performData) external override {
uint256 canvasId = abi. decode( performData, ( uint256 ));
vrfAddress. call(
abi. encodeWithSignature(( 'requestVRF(uint256)' ),
canvasId
));
}