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
));
}
|