DreamTimeToken.sol

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

import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";

/// @title DreamTimeToken
/// @notice ERC20 utility token used to reduce DreamNFT upgrade cooldowns. Each token reduces cooldown by 1 hour.
contract DreamTimeToken is 
    Initializable, 
    ERC20Upgradeable, 
    OwnableUpgradeable,
    UUPSUpgradeable 
{
    // Approved game contracts that are allowed to mint/burn tokens.
    mapping(address => bool) public gameContracts;

    event GameContractStatusChanged(address indexed contractAddress, bool status);

    /// @custom:oz-upgrades-unsafe-allow constructor
    constructor() {
        _disableInitializers();
    }

    /**
     * @dev Initializer that replaces the constructor
     * @param initialOwner The initial owner of the contract
     */
    function initialize(address initialOwner) public initializer {
        __ERC20_init("Time Token", "TT");
        __Ownable_init(initialOwner);
        __UUPSUpgradeable_init();
        
        // Mint 1000 tokens (plus decimals) to the owner
        _mint(initialOwner, 1000 * 10**decimals());
    }

    /**
     * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract.
     */
    function _authorizeUpgrade(address newImplementation) internal virtual override onlyOwner {}

    modifier onlyGameContracts() {
        require(gameContracts[msg.sender], "DreamTimeToken: Not authorized");
        _;
    }

    /**
     * @notice Mint Time Tokens to a specific address. Callable only by approved game contracts.
     */
    function mint(address to, uint256 amount) external onlyGameContracts {
        _mint(to, amount);
    }

    /**
     * @notice Burn Time Tokens from a specific address. Callable only by approved game contracts.
     */
    function burn(address from, uint256 amount) external onlyGameContracts {
        _burn(from, amount);
    }

    /**
     * @notice Set or unset a game contract's approval status for mint/burn privileges.
     * @param contractAddress The address of the game contract.
     * @param status True to approve, False to revoke.
     */
    function setGameContract(address contractAddress, bool status) external onlyOwner {
        require(contractAddress != address(0), "DreamTimeToken: Zero address not allowed");
        gameContracts[contractAddress] = status;
        emit GameContractStatusChanged(contractAddress, status);
    }
}