// SPDX-License-Identifier: MIT // An example of a consumer contract that directly pays for each request. pragma solidity ^0.8.20; import {ConfirmedOwner} from "@chainlink/contracts@1.5.0/src/v0.8/shared/access/ConfirmedOwner.sol"; import {LinkTokenInterface} from "@chainlink/contracts@1.5.0/src/v0.8/shared/interfaces/LinkTokenInterface.sol"; import {VRFV2PlusWrapperConsumerBase} from "@chainlink/contracts@1.5.0/src/v0.8/vrf/dev/VRFV2PlusWrapperConsumerBase.sol"; import {VRFV2PlusClient} from "@chainlink/contracts@1.5.0/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol"; /** * Request testnet LINK and ETH here: https://faucets.chain.link/ * Find information on LINK Token Contracts and get the latest ETH and LINK faucets here: * https://docs.chain.link/docs/link-token-contracts/ */ /** * THIS IS AN EXAMPLE CONTRACT THAT USES HARDCODED VALUES FOR CLARITY. * THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE. * DO NOT USE THIS CODE IN PRODUCTION. */ contract DirectFundingConsumer is VRFV2PlusWrapperConsumerBase, ConfirmedOwner { event RequestSent(uint256 requestId, uint32 numWords); event RequestFulfilled(uint256 requestId, uint256[] randomWords, uint256 payment); struct RequestStatus { uint256 paid; // amount paid in link bool fulfilled; // whether the request has been successfully fulfilled uint256[] randomWords; } mapping(uint256 => RequestStatus) public s_requests; /* requestId --> requestStatus */ // past requests Id. uint256[] public requestIds; uint256 public lastRequestId; // Depends on the number of requested values that you want sent to the // fulfillRandomWords() function. Test and adjust // this limit based on the network that you select, the size of the request, // and the processing of the callback request in the fulfillRandomWords() // function. uint32 public callbackGasLimit = 100_000; // The default is 3, but you can set this higher. uint16 public requestConfirmations = 3; // For this example, retrieve 2 random values in one request. // Cannot exceed VRFV2Wrapper.getConfig().maxNumWords. uint32 public numWords = 2; // Address LINK - hardcoded for Sepolia address public linkAddress = 0x779877A7B0D9E8603169DdbD7836e478b4624789; // address WRAPPER - hardcoded for Sepolia address public wrapperAddress = 0x195f15F2d49d693cE265b4fB0fdDbE15b1850Cc1; constructor() ConfirmedOwner(msg.sender) VRFV2PlusWrapperConsumerBase(wrapperAddress) {} function requestRandomWords( bool enableNativePayment ) external onlyOwner returns (uint256) { bytes memory extraArgs = VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: enableNativePayment})); uint256 requestId; uint256 reqPrice; if (enableNativePayment) { (requestId, reqPrice) = requestRandomnessPayInNative(callbackGasLimit, requestConfirmations, numWords, extraArgs); } else { (requestId, reqPrice) = requestRandomness(callbackGasLimit, requestConfirmations, numWords, extraArgs); } s_requests[requestId] = RequestStatus({paid: reqPrice, randomWords: new uint256[](0), fulfilled: false}); requestIds.push(requestId); lastRequestId = requestId; emit RequestSent(requestId, numWords); return requestId; } function fulfillRandomWords( uint256 _requestId, uint256[] memory _randomWords ) internal override { require(s_requests[_requestId].paid > 0, "request not found"); s_requests[_requestId].fulfilled = true; s_requests[_requestId].randomWords = _randomWords; emit RequestFulfilled(_requestId, _randomWords, s_requests[_requestId].paid); } function getRequestStatus( uint256 _requestId ) external view returns (uint256 paid, bool fulfilled, uint256[] memory randomWords) { require(s_requests[_requestId].paid > 0, "request not found"); RequestStatus memory request = s_requests[_requestId]; return (request.paid, request.fulfilled, request.randomWords); } /** * Allow withdraw of Link tokens from the contract */ function withdrawLink() public onlyOwner { LinkTokenInterface link = LinkTokenInterface(linkAddress); require(link.transfer(msg.sender, link.balanceOf(address(this))), "Unable to transfer"); } /// @notice withdrawNative withdraws the amount specified in amount to the owner /// @param amount the amount to withdraw, in wei function withdrawNative( uint256 amount ) external onlyOwner { (bool success,) = payable(owner()).call{value: amount}(""); // solhint-disable-next-line gas-custom-errors require(success, "withdrawNative failed"); } event Received(address, uint256); receive() external payable { emit Received(msg.sender, msg.value); } }