Factory.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import {Giveaway} from "src/Giveaway.sol";
contract Factory {
using SafeERC20 for ERC20;
// Variables
address private _owner;
address private _linkToken;
address private _vrfWrapper;
// Events
event NewGiveaway(uint256 indexed giveawayId, address indexed giveawayAddress, uint256 indexed endTime);
// Modifiers
modifier onlyOwner() {
_onlyOwner();
_;
}
function _onlyOwner() internal view {
require(msg.sender == _owner, "Only factory owner can call");
}
// Constructor
constructor(address linkToken, address vrfWrapper) {
_owner = msg.sender;
_linkToken = linkToken;
_vrfWrapper = vrfWrapper;
}
receive() external payable {}
// Methods
function createGiveaway(
uint64 giveawayId,
address prizeToken,
uint256 prizeAmount,
uint64 duration,
uint32 minParticipants,
uint32 maxParticipants,
bytes calldata signature
) external payable {
// Validate owner signature
bytes32 messageHash =
keccak256(abi.encodePacked(giveawayId, prizeToken, prizeAmount, duration, minParticipants, maxParticipants));
address signer = ECDSA.recover(messageHash, signature);
require(signer == _owner, "Invalid owner signature");
// Create giveaway
Giveaway giveaway;
if (prizeToken == address(0)) {
// Prize is in ETH
require(msg.value >= prizeAmount, "Not enough ETH sent");
giveaway = new Giveaway{value: msg.value}(
giveawayId,
msg.sender,
prizeToken,
prizeAmount,
duration,
minParticipants,
maxParticipants,
_owner,
address(this),
_linkToken,
_vrfWrapper
);
} else {
// Prize is an ERC20 token
giveaway = new Giveaway(
giveawayId,
msg.sender,
prizeToken,
prizeAmount,
duration,
minParticipants,
maxParticipants,
_owner,
address(this),
_linkToken,
_vrfWrapper
);
ERC20(prizeToken).safeTransferFrom(msg.sender, address(giveaway), prizeAmount);
}
// Emit event
uint256 endTime = block.timestamp + duration;
emit NewGiveaway(giveawayId, address(giveaway), endTime);
}
function endGiveaway(address giveawayAddress, uint32 vrfCallbackGasLimit) external onlyOwner {
Giveaway giveaway = Giveaway(giveawayAddress);
// Check if giveaway is ready to be ended
(bool isReady, string memory reason) = giveaway.isGiveawayReadyToEnd();
require(isReady, reason);
// Estimate VRF request price
uint256 requestPrice = giveaway.i_vrfV2PlusWrapper().calculateRequestPrice(vrfCallbackGasLimit, 1);
// Check LINK balance
uint256 linkBalance = ERC20(_linkToken).balanceOf(address(this));
require(linkBalance >= requestPrice, "LINK balance is too low");
// Transfer LINK to giveaway contract
ERC20(_linkToken).safeTransfer(giveawayAddress, requestPrice);
// End giveaway
giveaway.endGiveaway(vrfCallbackGasLimit, requestPrice);
}
function transfer(address token, address receiver, uint256 amount) external onlyOwner {
if (amount == 0) return;
if (token == address(0)) {
(bool success,) = receiver.call{value: amount}("");
require(success, "Transfer failed");
} else {
ERC20(token).safeTransfer(receiver, amount);
}
}
}Loading...



