Abstract Testnet

Contract Diff Checker

Contract Name:
RafflePhaseTest

Contract Source Code:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

contract RafflePhaseTest {
    address public owner;
    uint256 public constant ticketPrice = 0.001 ether; // Prix du ticket fixé à 0.001 ETH
    bool public isOpen; // true = la vente de tickets est ouverte

    // Nombre de tickets achetés par chaque adresse
    mapping(address => uint256) public ticketsBought;
    // Liste des participants uniques (une seule entrée par adresse)
    address[] public participants;
    // Permet de savoir si une adresse est déjà référencée dans "participants"
    mapping(address => bool) private hasParticipated;

    uint256 public totalTickets; // total de tickets vendus (somme de tous les ticketsBought)

    // Événements pour la transparence
    event TicketPurchased(address indexed buyer, uint256 tickets);
    event LotteryOpened();
    event LotteryClosed();
    event FundsWithdrawn(uint256 amount);

    modifier onlyOwner() {
        require(msg.sender == owner, "Not owner");
        _;
    }

    constructor() {
        owner = msg.sender;
        isOpen = false; // La loterie est fermée au départ
    }

    /// @notice Ouvre la vente de tickets (appelée par l'owner quand tout est prêt)
    function openLottery() external onlyOwner {
        require(!isOpen, "Lottery already open");
        isOpen = true;
        emit LotteryOpened();
    }

    /// @notice Ferme la vente de tickets (appelée par l'owner quand c'est fini)
    function closeLottery() external onlyOwner {
        require(isOpen, "Lottery not open");
        isOpen = false;
        emit LotteryClosed();
    }

    /// @notice Achète `_numTickets` tickets en envoyant la valeur correspondante
    function buyTicket(uint256 _numTickets) external payable {
        require(isOpen, "Lottery not open");
        require(_numTickets > 0, "Must buy >= 1");
        require(msg.value == ticketPrice * _numTickets, "Wrong ETH amount");

        ticketsBought[msg.sender] += _numTickets;
        totalTickets += _numTickets;

        // si c'est la première fois que cette adresse achète
        if (!hasParticipated[msg.sender]) {
            hasParticipated[msg.sender] = true;
            participants.push(msg.sender);
        }

        emit TicketPurchased(msg.sender, _numTickets);
    }

    /// @notice Retire les fonds du contrat (les ETH payés pour les tickets)
    function withdrawFunds() external onlyOwner {
        require(!isOpen, "Close lottery first");
        require(address(this).balance > 0, "No funds to withdraw");

        uint256 balance = address(this).balance;
        address payable recipient = payable(owner);

        totalTickets = 0; // Réinitialisation pour éviter d'éventuelles re-entrances

        (bool sent, ) = recipient.call{value: balance}("");
        require(sent, "Withdraw failed");

        emit FundsWithdrawn(balance);
    }

    /// @notice Renvoie le nombre total de tickets vendus
    function getTotalTickets() external view returns (uint256) {
        return totalTickets;
    }

    /// @notice Renvoie le nombre de tickets achetés par un utilisateur
    function getUserTickets(address _user) external view returns (uint256) {
        return ticketsBought[_user];
    }

    /// @notice Renvoie le nombre total de participants (uniques)
    function getParticipantCount() external view returns (uint256) {
        return participants.length;
    }

    /// @notice Renvoie la liste de tous les participants
    function getAllParticipants() external view returns (address[] memory) {
        return participants;
    }
}

Please enter a contract address above to load the contract details and source code.

Context size (optional):