Introduction
This guide will show you how to write the lottery contract showcased during ZENCON.
Hardhat Configuration
require("@nomicfoundation/hardhat-toolbox");
let privateKey = 'test test test test test test test test test test test test';
/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {
networks: {
zeniq: {
url: "https://smart.zeniq.network:9545",
chainId: 383414847825,
accounts: [privateKey]
}
},
solidity: {
version: "0.8.19",
settings: {
optimizer: {
enabled: true,
runs: 200
}
}
},
}
Lottery Contract
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts/access/Ownable.sol";
contract Lottery is Ownable {
address[] public players;
address public lastWinner;
uint256 public winningPrize;
mapping(address => bool) public hasEntered;
event PlayerEntered(address indexed player);
event WinnerPicked(address indexed winner, uint256 amount);
// Function to enter the lottery (Função para participar na loteria)
function enter() public {
require(!hasEntered[msg.sender], "You have already entered the lottery");
players.push(msg.sender);
emit PlayerEntered(msg.sender);
hasEntered[msg.sender] = true;
}
// Function to set the winning prize (Função para definir o prêmio inicial)
function setWinningPrize() public payable onlyOwner {
require(winningPrize == 0, "Winning prize has already been set");
require(msg.value > 0, "Initial prize must be greater than 0");
winningPrize = msg.value;
}
// Function to pick a winner (Função para escolher um vencedor)
function pickWinner() public onlyOwner {
require(players.length > 0, "No players in the lottery");
require(winningPrize > 0, "Winning prize not set");
// Generate a pseudo-random number using last block and current time (Gerar um número pseudo-aleatório usando o último bloco e o horário atual)
uint256 randomNumber = uint256(keccak256(abi.encodePacked(block.prevrandao, block.timestamp, players)));
// Pick a winner based on the random number (Escolher um vencedor com base no número aleatório)
address winner = players[randomNumber % players.length];
// Transfer the winning prize to the winner (Transferir o prêmio acumulado para o vencedor)
payable(winner).transfer(winningPrize);
// Reset participant status
for (uint256 i = 0; i < players.length; i++) {
hasEntered[players[i]] = false;
}
// Reset the list of players and winning prize (Resetar a lista de participantes e o prêmio acumulado)
delete players;
winningPrize = 0;
emit WinnerPicked(winner, winningPrize);
lastWinner = winner;
}
// Function to get the list of players (Função para obter a lista de participantes)
function getPlayers() public view returns (address[] memory) {
return players;
}
}
Deploying the Contract
// We require the Hardhat Runtime Environment explicitly here. This is optional
// but useful for running the script in a standalone fashion through `node <script>`.
//
// You can also run a script with `npx hardhat run <script>`. If you do that, Hardhat
// will compile your contracts, add the Hardhat Runtime Environment's members to the
// global scope, and execute the script.
const hre = require("hardhat");
async function main() {
const lottery = await hre.ethers.deployContract("Lottery");
await lottery.waitForDeployment();
console.log(`Lottery contract address`, lottery.target);
}
// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});