ETH Price: $3,264.74 (+3.46%)

Contract Diff Checker

Contract Name:
RedactedWagers

Contract Source Code:

File 1 of 1 : RedactedWagers

/*
Website: https://chiraq.bet/game
Telegram: https://t.me/chiraqcoin
Buy: https://app.uniswap.org/#/swap?outputCurrency=0xb8747b1a92c0db35bef62737bd3e91cf7cedf8ee&chain=ethereum


â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▒█▒░░░░░░░░░░░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▒▓▓▒░░░░░░░░░░░░░░░░░░░░░░▒█████▓░░░░░░░░░░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░░░░░░░░▒▓██▓░░░░░▓█████▓░░░░░░░░░░░░░░░░░░▒████▓▒▓██▓░░░░░░░░░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░░░░░░░█████░░░░░███████░░░░░░░░░░░░░░░░▒████▓▒░░░░▒███░░░░░░░░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░░░░░▒█████░░░░░███████▒░░░░░░░░░░░░░▓████▓▒░░░░░░▓████▒░░░░░░░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░░░░░▓███▒░░░░▒███████▓░░░░░░░░░░░▓████▓▒░░░░░░▓████▓░░░░░░░░░░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░░░░░░░░░░░░░▒████████░░░░░░░░░▒████▓▒░░░░░░▓████▓░░░░░░░░░░░░░░░░░░░░░░░░░░
░░░░░░░░▒▓▓▓▓▒▒░░░░░░░░░░▒█████████▓░░░░░░░░░░███▒░░░░░▒████▓░░░░░▒▓██████▓▒░░░░░░░░░░░░░░
░░░░░░▓███████████▓▓▓▓▓▓████████████░░░░░░░░░░░███▒░░░░░███▒░░░░▓████▓▒▒▒▓███▒░░░░░░░░░░░░
░░░░▒████████████████████████████████▒░░░░░░░░░░███▒░░░░░▓██▓░▒███▓░░░░░░░░███░░░░░░░░░░░░
░░░▒███████████████████████████████████▓░░░░░░░░░▓██▓░░░░░▓██████░░░░░░░░░░▓██▒░░░░░░░░░░░
░░░██████████████████████████▓▓▓▓▓█████▒░░░░░░░░░░▓██▓░░░░░▒███▓░░░░░░░░░░░▓██▒░░░░░░░░░░░
░░░████████████████████████░░░░░░░░░░░░░░░░░░░░░░░░▒███░░░░░░██░░░░░░░░░░░▓██▓░░░░░░░░░░░░
░░░▒█████████████████████▓░░░▓████▓▓░░░░▓███▒░░░░░░▒███▓░░░░░░░░░░░░░░░░░▓███░░░░░░░░░░░░░
░░░░░███████████████████▓░░░░███████▓░░░░░▒░░░░░░▒████░░░░░░░░░░░░░░░░░▓███▒░░░░░░░░░░░░░░
░░░░░░▒████████████████▓░░░░░░▒▓▓▓▓▒░░░░░░░░░░░░▓███▒░░░░░░░░░░░░░▓██████▒░░░░░░░░░░░░░░░░
░░░░░░░░░▒▓███████████▓░░░░░░░░░░░░░░███░░░░░░▓███▒░░░░░░░░░░░░░░░▒███▒░░░░░░░░░░░░░░░░░░░
░░░░░░░░░░░░░▒▒▒▓▓▓▒▒░░░░░░░░░░░░░░░░▒▒░░░░░▓███▒░░░░░░░░░░░░▓▒░░░░▓██▓░░░░░░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▓███▒░░░░░░░░░░░░▒███▒░░░░███░░░░░░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▒▓███▓░░░░░░░░░░░░░██████░░░░░███░░░░░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▒▓▓██████▓░░░░░░░░░░░░░▓███▒▒███░░░░▒██▓░░░░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░░░░░░░░░░░░░▒▓▓██████▓▒▒░░░░░░░░░░░░░░░▒███▒░░░▒███░░░░███▒░░░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░░░░░░░░░░░█████▓▒▒░░░░░░░░░░░░░░░░░░░▒███▓░░░░░░███▓░░░░███░░░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░░░░░░░░░░▓██▓░░░░░░░░░░░░░▒▒▓▓░░░░░░▓███░░░░░░▓███▒░░░░░████░░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░░░░░░░░░░███░░░░░░▒▒▓▓████████▓░░░░▒███░░░░░▓███▓░░░░▒████▒░░░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░░░░░░░░░▒██▓░░░░██████▓▓▒▒░░███░░░░░███░░░▓███▓░░░░▒███▓▒░░░░░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░░░░░░░░░▓██▒░░░▒██▓░░░░░░░░░▒██▓░░░░▒██▓░░▒███▓░░▓███▓░░░░░░░░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░░░░░░░░░███░░░░███░░░░░░░░░░░███▒░░░░███░░░░▓██████▒░░░░░░░░░░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░░░░░░░░▒██▒░░░▒███░░░░░░░░░░░░███░░░░▒███▒░░░░██▓▒░░░░░░░░░░░░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░░░░░░░░███░░░░▓██▒░░░░░░░░░░░░▓██▒░░░░▒████▓▒░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░░▒▒▓▓▓▓██▓░░░░███░░░░░░░░░░░░░░███▓░░░░░░▒▓███▓▒░░░░░░░░░░░░░░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░▒████████▒░░░▓██▒░░░░░░░░░░░░░░░▓████▓▒░░░░░▒▓████▒░░░░░░░░░░░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░▒██▓░░░░░░░░░███░░░░░░░░░░░░░░░░░░░▒████▓▒░░░░░▒▓████▒░░░░░░░░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░▒██▓░▒▒▒▒▒▒▒▓██▒░░░░░░░░░░░░░░░░░░░░░░▒▓████░░░░░▓██▓░░░░░░░░░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░▒██████████████░░░░░░░░░░░░░░░░░░░░░░░░▒███░░░░░███▒░░░░░░░░░░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░░▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▓███░░░░▒███░░░░░░░░░░░░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▒████▓▒░▓██▓░░░░░░░░░░░░░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▒▓█████▒░░░░░░░░░░░░░░░░░░░░░░░░░░░
â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–’â–“â–“â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘

*/
// File: contracts/BetCOins/Ownable.sol


pragma solidity ^0.8.4;

/// @notice Simple single owner authorization mixin.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol)
/// @dev While the ownable portion follows [EIP-173](https://eips.ethereum.org/EIPS/eip-173)
/// for compatibility, the nomenclature for the 2-step ownership handover
/// may be unique to this codebase.
abstract contract Ownable {
    /*´:°â€¢.°+.*•´.*:Ëš.°*.˚•´.°:°â€¢.°â€¢.*•´.*:Ëš.°*.˚•´.°:°â€¢.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+Ëš.*°.Ëš:*.´â€¢*.+°.•°:´*.´â€¢*.•°.•°:°.´:•˚°.*°.Ëš:*.´+°.•*/

    /// @dev The caller is not authorized to call the function.
    error Unauthorized();

    /// @dev The `newOwner` cannot be the zero address.
    error NewOwnerIsZeroAddress();

    /// @dev The `pendingOwner` does not have a valid handover request.
    error NoHandoverRequest();

    /*´:°â€¢.°+.*•´.*:Ëš.°*.˚•´.°:°â€¢.°â€¢.*•´.*:Ëš.°*.˚•´.°:°â€¢.°+.*•´.*:*/
    /*                           EVENTS                           */
    /*.•°:°.´+Ëš.*°.Ëš:*.´â€¢*.+°.•°:´*.´â€¢*.•°.•°:°.´:•˚°.*°.Ëš:*.´+°.•*/

    /// @dev The ownership is transferred from `oldOwner` to `newOwner`.
    /// This event is intentionally kept the same as OpenZeppelin's Ownable to be
    /// compatible with indexers and [EIP-173](https://eips.ethereum.org/EIPS/eip-173),
    /// despite it not being as lightweight as a single argument event.
    event OwnershipTransferred(address indexed oldOwner, address indexed newOwner);

    /// @dev An ownership handover to `pendingOwner` has been requested.
    event OwnershipHandoverRequested(address indexed pendingOwner);

    /// @dev The ownership handover to `pendingOwner` has been canceled.
    event OwnershipHandoverCanceled(address indexed pendingOwner);

    /// @dev `keccak256(bytes("OwnershipTransferred(address,address)"))`.
    uint256 private constant _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE =
        0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0;

    /// @dev `keccak256(bytes("OwnershipHandoverRequested(address)"))`.
    uint256 private constant _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE =
        0xdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d;

    /// @dev `keccak256(bytes("OwnershipHandoverCanceled(address)"))`.
    uint256 private constant _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE =
        0xfa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92;

    /*´:°â€¢.°+.*•´.*:Ëš.°*.˚•´.°:°â€¢.°â€¢.*•´.*:Ëš.°*.˚•´.°:°â€¢.°+.*•´.*:*/
    /*                          STORAGE                           */
    /*.•°:°.´+Ëš.*°.Ëš:*.´â€¢*.+°.•°:´*.´â€¢*.•°.•°:°.´:•˚°.*°.Ëš:*.´+°.•*/

    /// @dev The owner slot is given by: `not(_OWNER_SLOT_NOT)`.
    /// It is intentionally choosen to be a high value
    /// to avoid collision with lower slots.
    /// The choice of manual storage layout is to enable compatibility
    /// with both regular and upgradeable contracts.
    uint256 private constant _OWNER_SLOT_NOT = 0x8b78c6d8;

    /// The ownership handover slot of `newOwner` is given by:
    /// ```
    ///     mstore(0x00, or(shl(96, user), _HANDOVER_SLOT_SEED))
    ///     let handoverSlot := keccak256(0x00, 0x20)
    /// ```
    /// It stores the expiry timestamp of the two-step ownership handover.
    uint256 private constant _HANDOVER_SLOT_SEED = 0x389a75e1;

    /*´:°â€¢.°+.*•´.*:Ëš.°*.˚•´.°:°â€¢.°â€¢.*•´.*:Ëš.°*.˚•´.°:°â€¢.°+.*•´.*:*/
    /*                     INTERNAL FUNCTIONS                     */
    /*.•°:°.´+Ëš.*°.Ëš:*.´â€¢*.+°.•°:´*.´â€¢*.•°.•°:°.´:•˚°.*°.Ëš:*.´+°.•*/

    /// @dev Initializes the owner directly without authorization guard.
    /// This function must be called upon initialization,
    /// regardless of whether the contract is upgradeable or not.
    /// This is to enable generalization to both regular and upgradeable contracts,
    /// and to save gas in case the initial owner is not the caller.
    /// For performance reasons, this function will not check if there
    /// is an existing owner.
    function _initializeOwner(address newOwner) internal virtual {
        /// @solidity memory-safe-assembly
        assembly {
            // Clean the upper 96 bits.
            newOwner := shr(96, shl(96, newOwner))
            // Store the new value.
            sstore(not(_OWNER_SLOT_NOT), newOwner)
            // Emit the {OwnershipTransferred} event.
            log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)
        }
    }

    /// @dev Sets the owner directly without authorization guard.
    function _setOwner(address newOwner) internal virtual {
        /// @solidity memory-safe-assembly
        assembly {
            let ownerSlot := not(_OWNER_SLOT_NOT)
            // Clean the upper 96 bits.
            newOwner := shr(96, shl(96, newOwner))
            // Emit the {OwnershipTransferred} event.
            log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)
            // Store the new value.
            sstore(ownerSlot, newOwner)
        }
    }

    /// @dev Throws if the sender is not the owner.
    function _checkOwner() internal view virtual {
        /// @solidity memory-safe-assembly
        assembly {
            // If the caller is not the stored owner, revert.
            if iszero(eq(caller(), sload(not(_OWNER_SLOT_NOT)))) {
                mstore(0x00, 0x82b42900) // `Unauthorized()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /*´:°â€¢.°+.*•´.*:Ëš.°*.˚•´.°:°â€¢.°â€¢.*•´.*:Ëš.°*.˚•´.°:°â€¢.°+.*•´.*:*/
    /*                  PUBLIC UPDATE FUNCTIONS                   */
    /*.•°:°.´+Ëš.*°.Ëš:*.´â€¢*.+°.•°:´*.´â€¢*.•°.•°:°.´:•˚°.*°.Ëš:*.´+°.•*/

    /// @dev Allows the owner to transfer the ownership to `newOwner`.
    function transferOwnership(address newOwner) public payable virtual onlyOwner {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(shl(96, newOwner)) {
                mstore(0x00, 0x7448fbae) // `NewOwnerIsZeroAddress()`.
                revert(0x1c, 0x04)
            }
        }
        _setOwner(newOwner);
    }

    /// @dev Allows the owner to renounce their ownership.
    function renounceOwnership() public payable virtual onlyOwner {
        _setOwner(address(0));
    }

    /// @dev Request a two-step ownership handover to the caller.
    /// The request will be automatically expire in 48 hours (172800 seconds) by default.
    function requestOwnershipHandover() public payable virtual {
        unchecked {
            uint256 expires = block.timestamp + ownershipHandoverValidFor();
            /// @solidity memory-safe-assembly
            assembly {
                // Compute and set the handover slot to `expires`.
                mstore(0x0c, _HANDOVER_SLOT_SEED)
                mstore(0x00, caller())
                sstore(keccak256(0x0c, 0x20), expires)
                // Emit the {OwnershipHandoverRequested} event.
                log2(0, 0, _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE, caller())
            }
        }
    }

    /// @dev Cancels the two-step ownership handover to the caller, if any.
    function cancelOwnershipHandover() public payable virtual {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute and set the handover slot to 0.
            mstore(0x0c, _HANDOVER_SLOT_SEED)
            mstore(0x00, caller())
            sstore(keccak256(0x0c, 0x20), 0)
            // Emit the {OwnershipHandoverCanceled} event.
            log2(0, 0, _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE, caller())
        }
    }

    /// @dev Allows the owner to complete the two-step ownership handover to `pendingOwner`.
    /// Reverts if there is no existing ownership handover requested by `pendingOwner`.
    function completeOwnershipHandover(address pendingOwner) public payable virtual onlyOwner {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute and set the handover slot to 0.
            mstore(0x0c, _HANDOVER_SLOT_SEED)
            mstore(0x00, pendingOwner)
            let handoverSlot := keccak256(0x0c, 0x20)
            // If the handover does not exist, or has expired.
            if gt(timestamp(), sload(handoverSlot)) {
                mstore(0x00, 0x6f5e8818) // `NoHandoverRequest()`.
                revert(0x1c, 0x04)
            }
            // Set the handover slot to 0.
            sstore(handoverSlot, 0)
        }
        _setOwner(pendingOwner);
    }

    /*´:°â€¢.°+.*•´.*:Ëš.°*.˚•´.°:°â€¢.°â€¢.*•´.*:Ëš.°*.˚•´.°:°â€¢.°+.*•´.*:*/
    /*                   PUBLIC READ FUNCTIONS                    */
    /*.•°:°.´+Ëš.*°.Ëš:*.´â€¢*.+°.•°:´*.´â€¢*.•°.•°:°.´:•˚°.*°.Ëš:*.´+°.•*/

    /// @dev Returns the owner of the contract.
    function owner() public view virtual returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := sload(not(_OWNER_SLOT_NOT))
        }
    }

    /// @dev Returns the expiry timestamp for the two-step ownership handover to `pendingOwner`.
    function ownershipHandoverExpiresAt(address pendingOwner)
        public
        view
        virtual
        returns (uint256 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the handover slot.
            mstore(0x0c, _HANDOVER_SLOT_SEED)
            mstore(0x00, pendingOwner)
            // Load the handover slot.
            result := sload(keccak256(0x0c, 0x20))
        }
    }

    /// @dev Returns how long a two-step ownership handover is valid for in seconds.
    function ownershipHandoverValidFor() public view virtual returns (uint64) {
        return 48 * 3600;
    }

    /*´:°â€¢.°+.*•´.*:Ëš.°*.˚•´.°:°â€¢.°â€¢.*•´.*:Ëš.°*.˚•´.°:°â€¢.°+.*•´.*:*/
    /*                         MODIFIERS                          */
    /*.•°:°.´+Ëš.*°.Ëš:*.´â€¢*.+°.•°:´*.´â€¢*.•°.•°:°.´:•˚°.*°.Ëš:*.´+°.•*/

    /// @dev Marks a function as only callable by the owner.
    modifier onlyOwner() virtual {
        _checkOwner();
        _;
    }
}
// File: @openzeppelin/contracts/security/ReentrancyGuard.sol


// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be _NOT_ENTERED
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
}

// File: @openzeppelin/contracts/token/ERC20/IERC20.sol


// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);
}

// File: contracts/BetCOins/RedactedWagersVersion.sol


pragma solidity ^0.8.21;




contract RedactedWagers is ReentrancyGuard, Ownable {
    IERC20 public chiraqToken;

    uint256 constant CONTRACT_FEE_PERCENT = 5;
    
    uint256 private contractBalance;

    uint256 public version;

    enum States {
        Open,
        Closed,
        Resolved
    }
    States public state = States.Resolved;

    mapping(uint256 => mapping(address => mapping(uint256 => uint256)))
        public betAmounts;
    mapping(uint256 => mapping(uint256 => uint256)) public totalPerOutcome;

    mapping(uint256 => mapping(address => uint16[])) public userPredictions;

    mapping(uint256 => uint256) public winningOutcome;
    mapping(uint256 => uint256) public total;

    event BetPlaced(
        address indexed user,
        uint256 prediction,
        uint256 amount,
        uint256 version
    );
    event BetResolved(uint256 winningOutcome, uint256 version);
    event Claimed(address indexed user, uint256 amount, uint256 version);
    event BettingOpened(uint256 version);
    event BettingClosed();

    constructor(IERC20 _chiraqToken) {
        _initializeOwner(msg.sender);
        chiraqToken = _chiraqToken;
    }

    /*´:°â€¢.°+.*•´.*:Ëš.°*.˚•´.°:°â€¢.°â€¢.*•´.*:Ëš.°*.˚•´.°:°â€¢.°+.*•´.*:*/
    /*               PUBLIC NON-PAYABLE FUNCTIONS                 */
    /*.•°:°.´+Ëš.*°.Ëš:*.´â€¢*.+°.•°:´*.´â€¢*.•°.•°:°.´:•˚°.*°.Ëš:*.´+°.•*/

    /**
     * @notice Function to place a bet
     * @param _prediction The prediction made by the bettor
     * @param _amount The bet amount
     */
    function murderWager(uint256 _prediction, uint256 _amount)
        public
        nonReentrant
    {
        require(state == States.Open);
        require(_prediction > 0, "Prediction cannot be zero");
        require(_amount >= 1000 * 1e18, "Bet amount must be greater than 0");

        uint256 betAmount = (_amount * (100 - CONTRACT_FEE_PERCENT)) / 100;

        chiraqToken.transferFrom(msg.sender, address(this), _amount);

        contractBalance += (_amount - betAmount);
        betAmounts[version][msg.sender][_prediction] += betAmount;
        totalPerOutcome[version][_prediction] += betAmount;
        total[version] += betAmount;

        userPredictions[version][msg.sender].push(uint16(_prediction));

        emit BetPlaced(msg.sender, _prediction, betAmount, version);
    }

    /**
     * @notice Function to claim winnings
     */
    function bloodMoney() public nonReentrant {
        require(state == States.Resolved, "Bet has not been resolved yet");
        uint256 currentOutcome = winningOutcome[version];
        require(
            betAmounts[version][msg.sender][currentOutcome] > 0,
            "No winnings to claim"
        );

        uint256 amount = (betAmounts[version][msg.sender][currentOutcome] *
            total[version]) / totalPerOutcome[version][currentOutcome];
        require(
            chiraqToken.balanceOf(address(this)) >= amount,
            "Not enough tokens to pay out"
        );

        betAmounts[version][msg.sender][currentOutcome] = 0;
        chiraqToken.transfer(msg.sender, amount);

        emit Claimed(msg.sender, amount, version);
    }

    /**
     * @notice Function to claim winnings from a previous version
     * @param _version The version from which to claim
     */
    function claimOldWinnings(uint256 _version) public nonReentrant {
        require(_version > 0);
        require(
            _version < version,
            "This function is only for claiming old winnings"
        );
        uint256 currentOutcome = winningOutcome[version];
        require(
            betAmounts[_version][msg.sender][currentOutcome] > 0,
            "No winnings to claim"
        );

        uint256 amount = (betAmounts[_version][msg.sender][currentOutcome] *
            total[version]) / totalPerOutcome[_version][currentOutcome];
        require(
            chiraqToken.balanceOf(address(this)) >= amount,
            "Not enough tokens to pay out"
        );

        betAmounts[_version][msg.sender][currentOutcome] = 0;
        chiraqToken.transfer(msg.sender, amount);

        emit Claimed(msg.sender, amount, version);
    }

    /*´:°â€¢.°+.*•´.*:Ëš.°*.˚•´.°:°â€¢.°â€¢.*•´.*:Ëš.°*.˚•´.°:°â€¢.°+.*•´.*:*/
    /*                  PUBLIC VIEW FUNCTIONS                     */
    /*.•°:°.´+Ëš.*°.Ëš:*.´â€¢*.+°.•°:´*.´â€¢*.•°.•°:°.´:•˚°.*°.Ëš:*.´+°.•*/

    /**
     * @notice Function to get the total bet amount for a particular outcome
     * @param _outcome The outcome to check
     * @return The total bet amount for the outcome
     */
    function getTotalBetsForOutcome(uint256 _outcome)
        public
        view
        returns (uint256)
    {
        return totalPerOutcome[version][_outcome];
    }

    /**
     * @notice Function to get the total bet amount of a user
     * @param _user The user to check
     * @return The total bet amount of the user
     */
    function getUserTotalBets(address _user) public view returns (uint256) {
        uint256 totalBets = 0;
        unchecked {
            for (
                uint256 i = 0;
                i < userPredictions[version][_user].length;
                i++
            ) {
                totalBets += betAmounts[version][_user][
                    userPredictions[version][_user][i]
                ];
            }
        }
        return totalBets;
    }

    /**
     * @notice Function to get the total bet amount a user has placed for a particular outcome
     * @param _user The user to check
     * @param _outcome The outcome to check
     * @return The total bet amount the user has placed for the outcome
     */
    function getUserPredictionForOutcome(address _user, uint256 _outcome)
        public
        view
        returns (uint256)
    {
        return betAmounts[version][_user][_outcome];
    }

    /**
     * @notice Function to get the total bet amount a user has placed for a particular outcome
     * @param _user The user to check
     * @param _outcomes The outcomes to check
     * @return amounts The total bet amounts the user has placed for the outcomes
     */
    function getUserPredictionForOutcomes(
        address _user,
        uint256[] memory _outcomes
    ) public view returns (uint256[] memory amounts) {
        amounts = new uint256[](_outcomes.length);
        unchecked {
            for (uint256 i = 0; i < _outcomes.length; i++) {
                amounts[i] = betAmounts[version][_user][_outcomes[i]];
            }
        }
        return amounts;
    }

    /**
     * @notice Function to get the total balance currently held in the contract
     * @return The total balance currently held in the contract
     */
    function getContractBalance() public view returns (uint256) {
        return contractBalance;
    }

    /**
     * @notice Function to get all outcomes a user has bet on
     * @param _user The address of the user
     * @return An array of outcomes the user has bet on
     */
    function getUserOutcomes(address _user)
        public
        view
        returns (uint16[] memory)
    {
        return userPredictions[version][_user];
    }

    /**
     * @notice Function to get amount to claim for current version     
     * @return amount The amount to claim
     */
    function getAmountToClaimCurrent() public view returns (uint256) {        
        if (betAmounts[version][msg.sender][winningOutcome[version]] == 0) {
            return 0;
        }

        uint256 amount = (betAmounts[version][msg.sender][
            winningOutcome[version]
        ] * total[version]) / totalPerOutcome[version][winningOutcome[version]];

        return amount;
    }

    /**
     * @notice Function to get amount to claim
     * @param _version The version from which to claim
     * @return amount The amount to claim
     */
    function getAmountToClaim(uint256 _version) public view returns (uint256) {
        require(_version > 0);
        require(_version <= version, "Version does not exist");

        if (betAmounts[_version][msg.sender][winningOutcome[_version]] == 0) {
            return 0;
        }

        uint256 amount = (betAmounts[_version][msg.sender][
            winningOutcome[_version]
        ] * total[version]) / totalPerOutcome[_version][winningOutcome[_version]];

        return amount;
    }

    /*´:°â€¢.°+.*•´.*:Ëš.°*.˚•´.°:°â€¢.°â€¢.*•´.*:Ëš.°*.˚•´.°:°â€¢.°+.*•´.*:*/
    /*               EXTERNAL ONLY-OWNER FUNCTIONS                */
    /*.•°:°.´+Ëš.*°.Ëš:*.´â€¢*.+°.•°:´*.´â€¢*.•°.•°:°.´:•˚°.*°.Ëš:*.´+°.•*/
    /**
     * @notice Function to close betting
     */
    function openBetting() external onlyOwner {
        require(state == States.Resolved);
        version++;
        state = States.Open;        

        emit BettingOpened(version);
    }

    /**
     * @notice Function to close betting
     */
    function closeBetting() external onlyOwner {
        require(state == States.Open);
        state = States.Closed;

        emit BettingClosed();
    }

    /**
     * @notice Function to resolve a bet
     * @param _winningOutcome The winning outcome
     */
    function resolveBet(uint256 _winningOutcome) external onlyOwner {
        require(state == States.Closed);
        winningOutcome[version] = _winningOutcome;
        state = States.Resolved;

        emit BetResolved(_winningOutcome, version);
    }

    /**
     * @notice Function to withdraw contract fees
     * @param recipient Address to receive the withdrawn fees
     */
    function withdrawContractFees(address recipient) external onlyOwner {
        uint256 balance = contractBalance;
        contractBalance = 0;
        // Transfer fees to the owner
        chiraqToken.transfer(recipient, balance);
    }
}

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

Context size (optional):