Problem Statement
You are tasked with creating a simple smart contract that simulates a basic lottery system. The contract should allow users to participate by sending an amount of Ether, and the winner will be selected randomly from all participants at a fixed interval (e.g., once every 24 hours). Winners receive all Ether collected in the lottery pool.
Requirements:
- Implement a function that allows users to buy a ticket by sending Ether. Each participant can enter multiple times but must send enough Ether each time they participate (minimum of 0.1 Ether).
- Once a day, randomly select one participant as the winner and transfer all Ether in the contract to this account.
- Emit an event whenever someone buys a ticket and when the lottery is won.
Considerations:
- Ensure that your solution is fair and not easily predictable.
- Handle potential issues such as what happens if there are no participants or if the random selection fails.
Concepts
- Solidity basics
- Events in Ethereum
- Reentrancy attacks
Constraints
- Minimum Ether per entry is 0.1 Ether
- Lottery should reset after every winner is declared
Security Notes
- Avoid reentrancy vulnerabilities in your transfer function
- Ensure randomness is achieved securely, possibly using blockhashes and timestamps
Solutions
Php Solution
pragma solidity ^0.8.0;
contract Lottery {
// Define an event that logs a ticket purchase
event TicketPurchased(address indexed buyer);
// Define an event that logs the lottery winner
event LotteryWon(address indexed winner, uint prizeAmount);
// Minimum amount of Ether required to buy a ticket
uint public constant MINIMUM_BET = 0.1 ether;
// Mapping to store all participants' addresses
address[] public players;
// The timestamp of the last lottery draw
uint public lastDrawTimestamp;
// Duration after which a new lottery draw is triggered (24 hours)
uint public constant LOTTERY_DURATION = 1 days;
// Constructor sets the initial timestamp
constructor() {
lastDrawTimestamp = block.timestamp;
}
// Function to buy a ticket. Participants must send at least MINIMUM_BET Ether.
function buyTicket() public payable {
require(msg.value >= MINIMUM_BET, "Minimum bet amount not met");
players.push(msg.sender);
emit TicketPurchased(msg.sender);
// Check if it's time to draw the lottery
checkAndDrawLottery();
}
// Function to securely select a winner using blockhash and timestamp
function selectWinner() internal {
require(players.length > 0, "No participants in the lottery");
uint index = uint(keccak256(abi.encodePacked(block.difficulty, block.timestamp))) % players.length;
address winner = players[index];
// Transfer all Ether to the winner
payable(winner).transfer(address(this).balance);
emit LotteryWon(winner, address(this).balance);
// Reset the lottery state
resetLottery();
}
// Function to check if it's time to draw the lottery and perform the draw
function checkAndDrawLottery() internal {
if (block.timestamp - lastDrawTimestamp >= LOTTERY_DURATION) {
selectWinner();
}
}
// Function to reset the state of the lottery for a new round
function resetLottery() internal {
delete players;
lastDrawTimestamp = block.timestamp;
}
} This Solidity smart contract implements a basic lottery system where participants can buy tickets by sending Ether. Each ticket purchase requires a minimum of 0.1 Ether, and all funds are pooled until a winner is selected once every 24 hours.
The contract maintains a list of participant addresses in the `players` array and keeps track of when the last draw occurred with `lastDrawTimestamp`. The `buyTicket()` function handles ticket purchases, ensuring that each purchase meets the minimum bet requirement. It also checks if enough time has passed since the last draw to trigger a new lottery round.
The `selectWinner()` function securely selects a winner using a pseudo-random number generated from the block difficulty and timestamp. This method helps achieve randomness without relying on external sources. The selected winner receives all Ether in the contract, and the contract state is reset for the next round through the `resetLottery()` function.
Events are emitted whenever a ticket is purchased or when the lottery is won to provide transparency and allow front-end applications to listen for these actions. Security considerations include avoiding reentrancy vulnerabilities by using internal functions for sensitive operations and ensuring randomness in the winner selection process.