Skip to content

Commit 3d9accf

Browse files
Omid BodaghiOmid Bodaghi
authored andcommitted
Add chainlink automation
1 parent fb18a7c commit 3d9accf

File tree

7 files changed

+147
-57
lines changed

7 files changed

+147
-57
lines changed

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
[submodule "lib/forge-std"]
22
path = lib/forge-std
33
url = https://github.com/foundry-rs/forge-std
4+
[submodule "lib/chainlink-brownie-contracts"]
5+
path = lib/chainlink-brownie-contracts
6+
url = https://github.com/smartcontractkit/chainlink-brownie-contracts

foundry.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@
22
src = "src"
33
out = "out"
44
libs = ["lib"]
5+
remappings = ['@chainlink/contracts/=lib/chainlink-brownie-contracts/contracts/']
56

67
# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options

lib/chainlink-brownie-contracts

script/Counter.s.sol

Lines changed: 0 additions & 19 deletions
This file was deleted.

src/Counter.sol

Lines changed: 0 additions & 14 deletions
This file was deleted.

src/Raffle.sol

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.28;
3+
4+
import {VRFConsumerBaseV2Plus} from "@chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol";
5+
import {VRFV2PlusClient} from "@chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol";
6+
7+
/**
8+
* @title A sample Raffle contract
9+
* @author Omid Bodaghi
10+
* @notice This contract is for creating a sample raffle
11+
* @dev Implements Chainlink VRFv2.5
12+
*/
13+
contract Raffle is VRFConsumerBaseV2Plus {
14+
/* Errors */
15+
error Raffle__SendMoreToEnterRaffle();
16+
error Raffle__TransferFailed();
17+
error Raffle__RaffleNotOpen();
18+
error Raffle__UpkeepNotNeeded(uint256 balance, uint256 playersLength, uint256 raffleState);
19+
20+
/* Type Declarations*/
21+
enum RaffleState {
22+
OPEN,
23+
CALCULATING
24+
}
25+
26+
/* State Variables*/
27+
uint16 private constant REQUEST_CONFIRMATIONS = 3;
28+
uint32 private constant NUM_WORDS = 1;
29+
30+
uint256 private immutable i_entranceFee;
31+
// @dev The duration of the lottery in seconds
32+
uint256 private immutable i_interval;
33+
bytes32 private immutable i_keyHash;
34+
uint256 private immutable i_subscriptionId;
35+
uint32 private immutable i_callbackGasLimit;
36+
37+
address payable[] private s_players;
38+
uint256 private s_lastTimeStamp;
39+
address private s_recentWinner;
40+
RaffleState private s_raffleState;
41+
42+
/* Events */
43+
event RaffleEntered(address indexed player);
44+
event WinnerPicked(address indexed winner);
45+
46+
constructor(
47+
uint256 entranceFee,
48+
uint256 interval,
49+
address vrfCordinator,
50+
bytes32 gasLane,
51+
uint256 subscriptionId,
52+
uint32 callbackGasLimit
53+
) VRFConsumerBaseV2Plus(vrfCordinator) {
54+
i_entranceFee = entranceFee;
55+
i_interval = interval;
56+
i_keyHash = gasLane;
57+
i_subscriptionId = subscriptionId;
58+
i_callbackGasLimit = callbackGasLimit;
59+
60+
s_lastTimeStamp = block.timestamp;
61+
s_raffleState = RaffleState.OPEN;
62+
}
63+
64+
function enterRaffle() external payable {
65+
if (msg.value < i_entranceFee) {
66+
revert Raffle__SendMoreToEnterRaffle();
67+
}
68+
69+
if (s_raffleState != RaffleState.OPEN) {
70+
revert Raffle__RaffleNotOpen();
71+
}
72+
73+
s_players.push(payable(msg.sender));
74+
emit RaffleEntered(msg.sender);
75+
}
76+
77+
/**
78+
* @dev This is the function that Chainlink nodes will call to see if the lottery is reaady
79+
* to have a winner picked.
80+
* The following should be true in order for upkeepNeeded to be true:
81+
* 1. The time interval has passed between raffle runs.
82+
* 2. The lottery is open.
83+
* 3. The contract has ETH (has players).
84+
* 4. Implicitly, your subscription has LINK.
85+
*/
86+
function checkUpKeeper(bytes memory /* checkData */ )
87+
public
88+
view
89+
returns (bool upkeepNeeded, bytes memory /* performData */ )
90+
{
91+
bool timeHasPassed = (block.timestamp - s_lastTimeStamp) >= i_interval;
92+
bool isOpen = s_raffleState == RaffleState.OPEN;
93+
bool hasBalance = address(this).balance > 0;
94+
bool hasPlayers = s_players.length > 0;
95+
upkeepNeeded = timeHasPassed && isOpen && hasBalance && hasPlayers;
96+
return (upkeepNeeded, "");
97+
}
98+
99+
function performUpkeep(bytes calldata /* performData */ ) external {
100+
(bool upkeepNeeded,) = checkUpKeeper("");
101+
if (!upkeepNeeded) {
102+
revert Raffle__UpkeepNotNeeded(address(this).balance, s_players.length, uint256(s_raffleState));
103+
}
104+
105+
s_raffleState = RaffleState.CALCULATING;
106+
107+
VRFV2PlusClient.RandomWordsRequest memory request = VRFV2PlusClient.RandomWordsRequest({
108+
keyHash: i_keyHash,
109+
subId: i_subscriptionId,
110+
requestConfirmations: REQUEST_CONFIRMATIONS,
111+
callbackGasLimit: i_callbackGasLimit,
112+
numWords: NUM_WORDS,
113+
// Set nativePayment to true to pay for VRF requests with Sepolia ETH instead of LINK
114+
extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: false}))
115+
});
116+
117+
s_vrfCoordinator.requestRandomWords(request);
118+
}
119+
120+
function fulfillRandomWords(uint256, /* requestId */ uint256[] calldata randomWords) internal override {
121+
uint256 indexOfWinner = randomWords[0] % s_players.length;
122+
address payable recentWinner = s_players[indexOfWinner];
123+
124+
s_recentWinner = recentWinner;
125+
s_raffleState = RaffleState.OPEN;
126+
s_players = new address payable[](0);
127+
s_lastTimeStamp = block.timestamp;
128+
129+
(bool success,) = recentWinner.call{value: address(this).balance}("");
130+
if (!success) {
131+
revert Raffle__TransferFailed();
132+
}
133+
emit WinnerPicked(s_recentWinner);
134+
}
135+
136+
/**
137+
* Getter Functions
138+
*/
139+
function getEntranceFee() external view returns (uint256) {
140+
return i_entranceFee;
141+
}
142+
}

test/Counter.t.sol

Lines changed: 0 additions & 24 deletions
This file was deleted.

0 commit comments

Comments
 (0)