// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {AggregatorV3Interface} from "../../shared/interfaces/AggregatorV3Interface.sol"; // Ideally this contract should inherit from VRFCoordinatorV2 and delegate calls to VRFCoordinatorV2 // However, due to exceeding contract size limit, the logic from VRFCoordinatorV2 is ported over to this contract contract VRFCoordinatorV2TestHelper { uint96 internal s_paymentAmount; AggregatorV3Interface public immutable LINK_ETH_FEED; struct Config { uint16 minimumRequestConfirmations; uint32 maxGasLimit; // Reentrancy protection. bool reentrancyLock; // stalenessSeconds is how long before we consider the feed price to be stale // and fallback to fallbackWeiPerUnitLink. uint32 stalenessSeconds; // Gas to cover oracle payment after we calculate the payment. // We make it configurable in case those operations are repriced. uint32 gasAfterPaymentCalculation; } int256 private s_fallbackWeiPerUnitLink; Config private s_config; constructor( address linkEthFeed // solhint-disable-next-line no-empty-blocks ) { LINK_ETH_FEED = AggregatorV3Interface(linkEthFeed); } function calculatePaymentAmountTest( uint256 gasAfterPaymentCalculation, uint32 fulfillmentFlatFeeLinkPPM, uint256 weiPerUnitGas ) external { s_paymentAmount = calculatePaymentAmount(gasleft(), gasAfterPaymentCalculation, fulfillmentFlatFeeLinkPPM, weiPerUnitGas); } error InvalidLinkWeiPrice(int256 linkWei); error PaymentTooLarge(); function getFeedData() private view returns (int256) { uint32 stalenessSeconds = s_config.stalenessSeconds; bool staleFallback = stalenessSeconds > 0; uint256 timestamp; int256 weiPerUnitLink; (, weiPerUnitLink,, timestamp,) = LINK_ETH_FEED.latestRoundData(); // solhint-disable-next-line not-rely-on-time if (staleFallback && stalenessSeconds < block.timestamp - timestamp) { weiPerUnitLink = s_fallbackWeiPerUnitLink; } return weiPerUnitLink; } // Get the amount of gas used for fulfillment function calculatePaymentAmount( uint256 startGas, uint256 gasAfterPaymentCalculation, uint32 fulfillmentFlatFeeLinkPPM, uint256 weiPerUnitGas ) internal view returns (uint96) { int256 weiPerUnitLink; weiPerUnitLink = getFeedData(); if (weiPerUnitLink <= 0) { revert InvalidLinkWeiPrice(weiPerUnitLink); } // (1e18 juels/link) (wei/gas * gas) / (wei/link) = juels uint256 paymentNoFee = (1e18 * weiPerUnitGas * (gasAfterPaymentCalculation + startGas - gasleft())) / uint256(weiPerUnitLink); uint256 fee = 1e12 * uint256(fulfillmentFlatFeeLinkPPM); if (paymentNoFee > (1e27 - fee)) { revert PaymentTooLarge(); // Payment + fee cannot be more than all of the link in existence. } return uint96(paymentNoFee + fee); } function getPaymentAmount() public view returns (uint96) { return s_paymentAmount; } }