LucidCore.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721URIStorageUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
contract LucidCore is
Initializable,
ERC721URIStorageUpgradeable,
OwnableUpgradeable,
UUPSUpgradeable
{
uint256 public constant MAX_SUPPLY = 1000;
uint256 public totalMinted;
// Tracks which cores have been redeemed
mapping(uint256 => bool) private _redeemed;
// Base URI storage
string private _baseTokenURI;
// Events
event CoreRedeemed(uint256 indexed tokenId, address indexed owner);
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}
/**
* @notice Initializes the contract replacing the constructor
* @param initialOwner The initial owner of the contract
*/
function initialize(address initialOwner) public initializer {
__ERC721URIStorage_init();
__ERC721_init("Lucid Core", "CORE");
__Ownable_init(initialOwner);
__UUPSUpgradeable_init();
}
/**
* @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract.
* Called by {upgradeTo} and {upgradeToAndCall}.
*/
function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}
function setBaseURI(string memory baseURI) external onlyOwner {
_baseTokenURI = baseURI;
}
function _baseURI() internal view override returns (string memory) {
return _baseTokenURI;
}
/**
* @notice Mint a new Lucid Core token
* @param to Address to mint the token to
*/
function mintCore(address to) external onlyOwner {
require(totalMinted < MAX_SUPPLY, "LucidCore: Max supply reached");
totalMinted++;
uint256 newTokenId = totalMinted;
_safeMint(to, newTokenId);
}
/**
* @notice Batch mint Lucid Core tokens
* @param to Address to mint the tokens to
* @param amount Number of tokens to mint
*/
function batchMintCore(address to, uint256 amount) external onlyOwner {
require(totalMinted + amount <= MAX_SUPPLY, "LucidCore: Would exceed max supply");
for(uint256 i = 0; i < amount; i++) {
totalMinted++;
_safeMint(to, totalMinted);
}
}
/**
* @notice Check if a core has been redeemed
* @param tokenId The token ID to check
*/
function isRedeemed(uint256 tokenId) external view returns (bool) {
return _redeemed[tokenId];
}
/**
* @notice Mark a core as redeemed. Only callable by owner (Dream Oracle)
* @param tokenId The token ID to redeem
*/
function redeemCore(uint256 tokenId) external onlyOwner {
require(ownerOf(tokenId) != address(0), "LucidCore: Nonexistent token");
require(!_redeemed[tokenId], "LucidCore: Already redeemed");
_redeemed[tokenId] = true;
emit CoreRedeemed(tokenId, ownerOf(tokenId));
}
function setTokenURI(uint256 tokenId, string memory newTokenURI) external onlyOwner {
require(ownerOf(tokenId) != address(0), "LucidCore: URI set of nonexistent token");
_setTokenURI(tokenId, newTokenURI);
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId)
public
view
override(ERC721URIStorageUpgradeable)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
}