This my solidy code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface AutomationCompatibleInterface {
function checkUpkeep(bytes calldata checkData) external returns (bool upkeepNeeded, bytes memory performData);
function performUpkeep(bytes calldata performData) external;
}
// File: AutoCtr.sol
// File: @chainlink/contracts/src/v0.8/interfaces/KeeperCompatibleInterface.sol
pragma solidity 0.8.19;
import {VRFConsumerBaseV2Plus} from "@chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol";
import {VRFV2PlusClient} from "@chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol";
/* Errors */
error Raffle__UpkeepNotNeeded(uint256 currentBalance, uint256 numPlayers, uint256 raffleState);
error Raffle__TransferFailed();
error Raffle__SendMoreToEnterRaffle();
error Raffle__RaffleNotOpen();
/**
* 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 Lottery is VRFConsumerBaseV2Plus, AutomationCompatibleInterface {
/* Type declarations */
enum RaffleState {
OPEN,
CALCULATING
}
// Lottery Variables
uint256 private immutable i_entranceFee;
uint256 private s_lastTimeStamp;
address payable[] private s_players;
address private s_recentWinner;
uint256 private immutable i_interval;
RaffleState private s_raffleState;
event RequestSent(uint256 requestId, uint32 numWords);
event RequestFulfilled(uint256 requestId, uint256[] randomWords);
event RaffleEnter(address indexed player);
event WinnerPicked(address indexed player);
event RequestedRaffleWinner(uint256 indexed requestId, bytes performData);
// Your subscription ID.
uint256 public immutable s_subscriptionId =
78560131474220272056099479679342269674716447265552668612386115994028644171414;
// Past request IDs.
uint256[] public requestIds;
uint256 public lastRequestId;
// The gas lane to use, which specifies the maximum gas price to bump to.
// For a list of available gas lanes on each network,
// see https://docs.chain.link/docs/vrf/v2-5/supported-networks
bytes32 public keyHash =
0x787d74caea10b2b357790d5b5247c2f63d1d91572a9846f780606e4d953677ae;
// Depends on the number of requested values that you want sent to the
// fulfillRandomWords() function. Storing each word costs about 20,000 gas,
// so 100,000 is a safe default for this example contract. 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 = 2500000;
// 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 VRFCoordinatorV2_5.MAX_NUM_WORDS.
uint32 public numWords = 1;
/**
* HARDCODED FOR SEPOLIA
* COORDINATOR: 0x9DdfaCa8183c41ad55329BdeeD9F6A8d53168B1B
* https://docs.chain.link/vrf/v2-5/supported-networks#sepolia-testnet
*/
constructor(
// uint256 subscriptionId,
uint256 entranceFee,
uint256 interval
) VRFConsumerBaseV2Plus(0x9DdfaCa8183c41ad55329BdeeD9F6A8d53168B1B) {
// s_subscriptionId = subscriptionId;
i_entranceFee = entranceFee;
s_raffleState = RaffleState.OPEN;
s_lastTimeStamp = block.timestamp;
i_interval = interval;
}
// Assumes the subscription is funded sufficiently.
function _requestRandomWords()
private
onlyOwner
returns (uint256 requestId)
{
// Will revert if subscription is not set and funded.
requestId = s_vrfCoordinator.requestRandomWords(
VRFV2PlusClient.RandomWordsRequest({
keyHash: keyHash,
subId: s_subscriptionId,
requestConfirmations: requestConfirmations,
callbackGasLimit: callbackGasLimit,
numWords: numWords,
extraArgs: VRFV2PlusClient._argsToBytes(
VRFV2PlusClient.ExtraArgsV1({nativePayment: false})
)
})
);
requestIds.push(requestId);
lastRequestId = requestId;
emit RequestSent(requestId, numWords);
return requestId;
}
function fulfillRandomWords(
uint256,
uint256[] calldata _randomWords
) internal override {
uint256 indexOfWinner = _randomWords[0] % s_players.length;
address payable recentWinner = s_players[indexOfWinner];
s_recentWinner = recentWinner;
s_players = new address payable[](0);
s_raffleState = RaffleState.OPEN;
s_lastTimeStamp = block.timestamp;
(bool success, ) = recentWinner.call{value: address(this).balance}("");
// require(success, "Transfer failed");
if (!success) {
revert Raffle__TransferFailed();
}
emit WinnerPicked(recentWinner);
}
function enterRaffle() public payable {
// require(msg.value >= i_entranceFee, "Not enough value sent");
// require(s_raffleState == RaffleState.OPEN, "Raffle is not open");
if (msg.value < i_entranceFee) {
revert Raffle__SendMoreToEnterRaffle();
}
if (s_raffleState != RaffleState.OPEN) {
revert Raffle__RaffleNotOpen();
}
s_players.push(payable(msg.sender));
// Emit an event when we update a dynamic array or mapping
// Named events with the function name reversed
emit RaffleEnter(msg.sender);
}
/**
* @dev This is the function that the Chainlink Keeper nodes call
* they look for `upkeepNeeded` to return True.
* the following should be true for this to return true:
* 1. The time interval has passed between raffle runs.
* 2. The lottery is open.
* 3. The contract has ETH.
* 4. Implicity, your subscription is funded with LINK.
*/
function checkUpkeep(
bytes memory checkData
)
public
view
override
returns (bool upkeepNeeded, bytes memory /* performData */)
{
bool isOpen = RaffleState.OPEN == s_raffleState;
bool timePassed = ((block.timestamp - s_lastTimeStamp) > i_interval);
bool hasPlayers = s_players.length > 0;
bool hasBalance = address(this).balance > 0;
if (timePassed && isOpen && hasBalance && hasPlayers) {
return (true, checkData);
} else {
return (false, checkData);
}
}
/**
* @dev Once `checkUpkeep` is returning `true`, this function is called
* and it kicks off a Chainlink VRF call to get a random winner.
*/
function performUpkeep(bytes calldata performData ) external override {
s_raffleState = RaffleState.CALCULATING;
uint256 requestId = _requestRandomWords();
emit RequestedRaffleWinner(requestId, performData);
}
function getRaffleState() public view returns (RaffleState) {
return s_raffleState;
}
function getNumWords() public view returns (uint256) {
return numWords;
}
function getRecentWinner() public view returns (address) {
return s_recentWinner;
}
function getPlayer(uint256 index) public view returns (address) {
return s_players[index];
}
function getLastTimeStamp() public view returns (uint256) {
return s_lastTimeStamp;
}
function getInterval() public view returns (uint256) {
return i_interval;
}
function getEntranceFee() public view returns (uint256) {
return i_entranceFee;
}
function getNumberOfPlayers() public view returns (uint256) {
return s_players.length;
}
}
Contract address: https://sepolia.etherscan.io/address/0xfd2eA75f66493eCF7F45072E01254c6d8C403a35#readContract
Automation detail:
https://automation.chain.link/sepolia/3269845219509365492688127324933702012403758002781625898657947000998001276879
When reading contract, the method of checkData
returns true
, but performUpkeep
did not execute.
Expect it to run automatically。
New contributor
贰东之声 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.