finish up lottery course

This commit is contained in:
han
2025-01-06 21:19:15 +07:00
parent b6fb56fd2c
commit 54dda02722
12 changed files with 601 additions and 17 deletions

View File

@@ -0,0 +1,44 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
import {Script} from "forge-std/Script.sol";
import {Raffle} from "src/Raffle.sol";
import {HelperConfig} from "script/HelperConfig.s.sol";
import {CreateSubscription, FundSubscription, AddConsumer} from "script/Interactions.s.sol";
contract DeployRaffle is Script {
function run() public {}
function deployContract() public returns(Raffle, HelperConfig) {
HelperConfig helperConfig = new HelperConfig();
// local => deploy mocks, get local config
// sepolia => get sepolia config
HelperConfig.NetworkConfig memory config = helperConfig.getConfig();
if (config.subscriptionId == 0) {
// create subscription
CreateSubscription createSubscription = new CreateSubscription();
(config.subscriptionId, config.vrfCoordinator) = createSubscription.createSubscription(config.vrfCoordinator, config.account);
// fund it!
FundSubscription fundSubscription = new FundSubscription();
fundSubscription.fundSubscription(config.vrfCoordinator, config.subscriptionId, config.link, config.account);
}
vm.startBroadcast(config.account);
Raffle raffle = new Raffle(
config.entranceFee,
config.interval,
config.vrfCoordinator,
config.gasLane,
config.subscriptionId,
config.callbackGasLimit
);
vm.stopBroadcast();
AddConsumer addConsumer = new AddConsumer();
addConsumer.addConsumer(address(raffle), config.vrfCoordinator, config.subscriptionId, config.account);
return (raffle, helperConfig);
}
}

View File

@@ -0,0 +1,93 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
import {Script} from "forge-std/Script.sol";
import {VRFCoordinatorV2_5Mock} from "@chainlink/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2_5Mock.sol";
import {LinkToken} from "test/mocks/LinkToken.sol";
abstract contract CodeConstants {
/* VRF Mock Values */
uint96 public MOCK_BASE_FEE = 0.25 ether;
uint96 public MOCK_GAS_PRICE_LINK = 1e9;
// LINK / ETH price
int256 public MOCK_WEI_PER_UINT_LINK = 4e15;
uint256 public constant ETH_SEPOLIA_CHAIN_ID = 11155111;
uint256 public constant LOCAL_CHAIN_ID = 31337;
}
contract HelperConfig is CodeConstants, Script {
error HelperConfig__InvalidChainId();
struct NetworkConfig {
uint256 entranceFee;
uint256 interval;
address vrfCoordinator;
bytes32 gasLane;
uint32 callbackGasLimit;
uint256 subscriptionId;
address link;
address account;
}
NetworkConfig public localNetworkConfig;
mapping(uint256 chainid => NetworkConfig) public networkConfigs;
constructor() {
networkConfigs[ETH_SEPOLIA_CHAIN_ID] = getSepoliaEthConfig();
}
function getConfigByChainId(uint256 chainId) public returns (NetworkConfig memory) {
if (networkConfigs[chainId].vrfCoordinator != address(0)) {
return networkConfigs[chainId];
} else if (chainId == LOCAL_CHAIN_ID) {
// get or create anvil eth config
return getOrCreateAnvilEthConfig();
} else {
revert HelperConfig__InvalidChainId();
}
}
function getConfig() public returns (NetworkConfig memory) {
return getConfigByChainId(block.chainid);
}
function getSepoliaEthConfig() public pure returns (NetworkConfig memory) {
return NetworkConfig({
entranceFee: 0.01 ether, // 1e16
interval: 30, // 30 seconds
vrfCoordinator: 0x9DdfaCa8183c41ad55329BdeeD9F6A8d53168B1B,
gasLane: 0x130dba50ad435d4ecc214aad0d5820474137bd68e7e77724144f27c3c377d3d4,
callbackGasLimit: 500000, // 500,000 gas
subscriptionId: 0,
link: 0x779877A7B0D9E8603169DdbD7836e478b4624789,
account: address(1)
});
}
function getOrCreateAnvilEthConfig() public returns (NetworkConfig memory) {
// check if already set network config
if (localNetworkConfig.vrfCoordinator != address(0)) {
return localNetworkConfig;
}
// deploy mocks and such
vm.startBroadcast();
VRFCoordinatorV2_5Mock vrfCoordinatorMock = new VRFCoordinatorV2_5Mock(MOCK_BASE_FEE, MOCK_GAS_PRICE_LINK, MOCK_WEI_PER_UINT_LINK);
LinkToken linkToken = new LinkToken();
vm.stopBroadcast();
localNetworkConfig = NetworkConfig({
entranceFee: 0.01 ether, // 1e16
interval: 30, // 30 seconds
vrfCoordinator: address(vrfCoordinatorMock),
// doesn't matter
gasLane: 0x130dba50ad435d4ecc214aad0d5820474137bd68e7e77724144f27c3c377d3d4,
callbackGasLimit: 500000, // 500,000 gas
subscriptionId: 0, // might have to fix
link: address(linkToken),
account: 0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38
});
return localNetworkConfig;
}
}

View File

@@ -0,0 +1,92 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
import {Script, console} from "forge-std/Script.sol";
import {HelperConfig, CodeConstants} from "script/HelperConfig.s.sol";
import {VRFCoordinatorV2_5Mock} from "@chainlink/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2_5Mock.sol";
import {LinkToken} from "test/mocks/LinkToken.sol";
import {DevOpsTools} from "lib/foundry-devops/src/DevOpsTools.sol";
contract CreateSubscription is Script {
function createSubscriptionUsingConfig() public returns (uint256, address) {
HelperConfig helperConfig = new HelperConfig();
address vrfCoordinator = helperConfig.getConfig().vrfCoordinator;
address account = helperConfig.getConfig().account;
// create subscription
(uint256 subId, ) = createSubscription(vrfCoordinator, account);
return (subId, vrfCoordinator);
}
function createSubscription(address vrfCoordinator, address account) public returns (uint256, address) {
console.log("Creating subscription on chain Id: ", block.chainid);
vm.startBroadcast(account);
uint256 subId = VRFCoordinatorV2_5Mock(vrfCoordinator).createSubscription();
vm.stopBroadcast();
console.log("Your subscription Id is: ", subId);
console.log("Please update the subscription Id in your HelperConfig.s.sol");
return (subId, vrfCoordinator);
}
function run() public {
createSubscriptionUsingConfig();
}
}
contract FundSubscription is Script, CodeConstants {
uint256 public constant FUND_AMOUNT = 3 ether; // equals to 3 LINK
function fundSubscriptionUsingConfig() public {
HelperConfig helperConfig = new HelperConfig();
address vrfCoordinator = helperConfig.getConfig().vrfCoordinator;
uint256 subscriptionId = helperConfig.getConfig().subscriptionId;
address linkToken = helperConfig.getConfig().link;
address account = helperConfig.getConfig().account;
fundSubscription(vrfCoordinator, subscriptionId, linkToken, account);
}
function fundSubscription(address vrfCoordinator, uint256 subscriptionId, address linkToken, address account) public {
console.log("Funding subscription: ", subscriptionId);
console.log("Using vrfCoordinator: ", vrfCoordinator);
console.log("On ChainiId: ", block.chainid);
if (block.chainid == LOCAL_CHAIN_ID) {
vm.startBroadcast();
VRFCoordinatorV2_5Mock(vrfCoordinator).fundSubscription(subscriptionId, FUND_AMOUNT * 100);
vm.stopBroadcast();
} else {
vm.startBroadcast(account);
LinkToken(linkToken).transferAndCall(vrfCoordinator, FUND_AMOUNT, abi.encode(subscriptionId));
vm.stopBroadcast();
}
}
function run() public {
fundSubscriptionUsingConfig();
}
}
contract AddConsumer is Script {
function addConsumerUsingConfig(address mostRecentlyDeployed) public {
HelperConfig helperConfig = new HelperConfig();
uint256 subId = helperConfig.getConfig().subscriptionId;
address vrfCoordinator = helperConfig.getConfig().vrfCoordinator;
address account = helperConfig.getConfig().account;
addConsumer(mostRecentlyDeployed, vrfCoordinator, subId, account);
}
function addConsumer(address contractToAddToVrf, address vrfCoordinator, uint256 subId, address account) public {
console.log("Adding consumer contract: ", contractToAddToVrf);
console.log("To vrfCoordinator: ", vrfCoordinator);
console.log("On ChainId: ", block.chainid);
vm.startBroadcast(account);
VRFCoordinatorV2_5Mock(vrfCoordinator).addConsumer(subId, contractToAddToVrf);
vm.stopBroadcast();
}
function run() external {
address mostRecentlyDeployed = DevOpsTools.get_most_recent_deployment("Raffle", block.chainid);
addConsumerUsingConfig(mostRecentlyDeployed);
}
}