Skip to main content


This guide will show you how to write the lottery contract showcased during ZENCON.

Hardhat Configuration

let privateKey = 'test test test test test test test test test test test test';

/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {
networks: {
zeniq: {
url: "",
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");

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)

// 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`,;

// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main().catch((error) => {
process.exitCode = 1;