Created
May 15, 2026 23:07
-
-
Save rfikki/649c683bc2475bb45932e6cfa27232a8 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // SPDX-License-Identifier: MIT | |
| pragma solidity ^0.8.24; | |
| import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; | |
| import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; | |
| import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; | |
| /** | |
| * @title Dinosaur Amber Vault | |
| * @notice Locks exactly 100 DINO to mint 1 dynamic Dinosaur NFT. | |
| * The NFT acts as a physical receipt for the 100-token lot. | |
| */ | |
| contract DinosaurVault is ERC721, ReentrancyGuard { | |
| IERC20 public immutable dinoToken; | |
| uint256 public constant TOKENS_PER_NFT = 100 * 10**18; | |
| uint256 private _nextId = 1; | |
| // Events | |
| event Incubated(address indexed user, uint256 indexed tokenId); | |
| event Shattered(address indexed user, uint256 indexed tokenId); | |
| constructor(address _dinoToken) ERC721("Dinosaur Vault", "DV-NFT") { | |
| dinoToken = IERC20(_dinoToken); | |
| } | |
| /** | |
| * @notice Locks 100 DINO and mints 1 NFT. | |
| * @dev User must have called approve() on the DINO contract first. | |
| */ | |
| function incubate() external nonReentrant { | |
| // Pull 100 DINO from the user and lock it in this contract | |
| require(dinoToken.transferFrom(msg.sender, address(this), TOKENS_PER_NFT), "Transfer failed"); | |
| uint256 tokenId = _nextId++; | |
| _mint(msg.sender, tokenId); | |
| emit Incubated(msg.sender, tokenId); | |
| } | |
| /** | |
| * @notice Burns the NFT and returns the 100 DINO lot to the owner. | |
| */ | |
| function shatter(uint256 tokenId) external nonReentrant { | |
| // Ensure only the owner can unlock the lot | |
| require(ownerOf(tokenId) == msg.sender, "Not the owner"); | |
| _burn(tokenId); | |
| // Return the 100 DINO back to the user | |
| require(dinoToken.transfer(msg.sender, TOKENS_PER_NFT), "Transfer failed"); | |
| emit Shattered(msg.sender, tokenId); | |
| } | |
| /** | |
| * @notice This function would interact with your Uniswap V4 Hook | |
| * to render the Upeg-style liquid metadata based on the current pool state. | |
| */ | |
| function tokenURI(uint256 tokenId) public view override returns (string memory) { | |
| _requireOwned(tokenId); | |
| // Here you will route to the Upeg SVG rendering logic | |
| // which reads the Uniswap V4 Hook state. | |
| return "data:application/json;base64,..."; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment