// Contract: MESCommitBasedRaffle
// Target function: function raffleCommit(uint256 amount_, uint256 tokenId_) external
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

//////////////////////////////////////////////////////////////////
//     __  ___         __  _                                    //
//    /  |/  /__ _____/ /_(_)__ ____  ___                       //
//   / /|_/ / _ `/ __/ __/ / _ `/ _ \(_-<                       //
//  /_/  /_/\_,_/_/  \__/_/\_,_/_//_/___/                       //
//                                                              //
//    _____                 _ __    ___                  __     //
//   / ___/__  __ _  __ _  (_) /_  / _ )___ ____ ___ ___/ /     //
//  / /__/ _ \/  ' \/  ' \/ / __/ / _  / _ `(_-</ -_) _  /      //
//  \___/\___/_/_/_/_/_/_/_/\__/ /____/\_,_/___/\__/\_,_/       //
//                                                              //
//     ___       ________                                       //
//    / _ \___ _/ _/ _/ /__                                     //
//   / , _/ _ `/ _/ _/ / -_)                                    //
//  /_/|_|\_,_/_//_//_/\__/                                     //
//                                                              //
//  by: 0xInuarashi.eth                                         //
////////////////////////////////////////////////////////////////// 

abstract contract Ownable {
    address public owner; 
    constructor() { owner = msg.sender; }
    modifier onlyOwner { require(owner == msg.sender, "Not Owner!"); _; }
    function transferOwnership(address new_) external onlyOwner { owner = new_; }
}

interface iCS {

    struct Character {
        // general info
        uint8 race_;
        uint8 renderType_;

        // equipment
        uint16 transponderId_;
        uint16 spaceCapsuleId_;

        // stats
        uint8 augments_;
        uint16 basePoints_;
        uint16 totalEquipmentBonus_;
    }

    function characters(uint256 tokenId_) external view returns (Character memory);
}

interface iMES {
    function transferFrom(address from_, address to_, uint256 amount_) external;
    function burn(address from_, uint256 amount_) external;
}

interface IERC721 {
    function balanceOf(address owner_) external view returns (uint256); 
}

contract MESCommitBasedRaffle is Ownable {

    // M a r t i a n  E s s e n c e 
    iMES public MES = iMES(0x3C2Eb40D25a4b2B5A068a959a40d57D63Dc98B95);

    // M a r t i a n s 
    IERC721 public Martians = IERC721(0x075854b315F2cd7eC490853Bc5589B09E546449f);

    // M a r t i a n s  C h a r a c t e r  S t o r a g e 
    iCS public CS = iCS(0xC7C40032E952F52F1ce7472913CDd8EeC89521c4);

    // For a commit-based raffle, we need to store somewhere the index of users as well
    // as user-data.

    // Then, we can pull a seed with provably-fair randomness and then use
    // that randomness as inertia for a compute-intensive on-chain result.

    // Gas cost is conscious in this contract.

    // First, we define an interia.
    bytes32 public raffleInertia;
    
    // We then have a inertia pull method.
    function pullRaffleInertia() external onlyOwner {
        // Pulling is a 1-time function.
        require(raffleInertia == 0,
            "Inertia already set");

        // A pseudo-random generated bytes32. For provably-fair, change this.
        raffleInertia = keccak256(abi.encodePacked(
            block.timestamp, block.difficulty, blockhash(block.number)));
    }

    // Now, we need to set some commit-based raffle logics.
    struct CommitData {
        address entrant; // 20 | 12
        uint64 entries; // 8 | 4
    }

    // 2 SSTORE are necessary to do this on-chain with flexibility.
    CommitData[] public commitData;
    function viewCommitData() external view returns (CommitData[] memory) {
        return commitData;
    }

    // Then, we set some raffle logics
    // uint256 public weiPerEntry = 1 ether;

    // Benchmark: 58,304 GAS Units
    // commitBasedRaffleOffChainERC20.sol: 43,431 GAS Units 

    // Numbers without any require statements and reading additional SSTORES...
    // 67,424 GAS Units per TX using ERC20I with full approval (no approve SSTORE update)
    // 70,677 GAS Units per TX using ERC20I with partial approval (approve SSTORE update)