1+ // SPDX-License-Identifier: MIT
2+ pragma solidity ^ 0.8.28 ;
3+
4+ import {ERC721 } from "@openzeppelin/contracts/token/ERC721/ERC721.sol " ;
5+ import {IMintableERC721} from "./IMintable.sol " ;
6+
7+ /// @title BridgedERC721
8+ /// @notice An ERC721 token that represents a bridged token from another chain
9+ /// @dev Only the bridge contract can mint and burn tokens
10+ contract BridgedERC721 is ERC721 , IMintableERC721 {
11+ /// @dev Mapping from token ID to custom token URI
12+ mapping (uint256 => string ) private _tokenURIs;
13+ /// @notice The bridge contract that can mint and burn tokens
14+ address public immutable bridge;
15+
16+ /// @notice The original token address on the source chain
17+ address public immutable originalToken;
18+
19+ /// @notice The source chain identifier (could be chain ID or other identifier)
20+ uint256 public immutable sourceChain;
21+
22+ error OnlyBridge ();
23+
24+ modifier onlyBridge () {
25+ if (msg .sender != bridge) revert OnlyBridge ();
26+ _;
27+ }
28+
29+ constructor (
30+ string memory name ,
31+ string memory symbol ,
32+ address _bridge ,
33+ address _originalToken ,
34+ uint256 _sourceChain
35+ ) ERC721 (name, symbol) {
36+ bridge = _bridge;
37+ originalToken = _originalToken;
38+ sourceChain = _sourceChain;
39+ }
40+
41+ /// @inheritdoc IMintableERC721
42+ function mint (address to , uint256 tokenId ) external onlyBridge {
43+ _mint (to, tokenId);
44+ }
45+
46+ /// @dev Mints a token with custom URI
47+ /// @param to Address to mint the token to
48+ /// @param tokenId Token ID to mint
49+ /// @param tokenURI_ Custom URI for this token
50+ function mintWithURI (address to , uint256 tokenId , string memory tokenURI_ ) external onlyBridge {
51+ _mint (to, tokenId);
52+ _setTokenURI (tokenId, tokenURI_);
53+ }
54+
55+ /// @inheritdoc IMintableERC721
56+ function burn (address from , uint256 tokenId ) external onlyBridge {
57+ _burn (tokenId);
58+ // Clear the token URI when burning
59+ if (bytes (_tokenURIs[tokenId]).length != 0 ) {
60+ delete _tokenURIs[tokenId];
61+ }
62+ }
63+
64+ /// @dev See {IERC721Metadata-tokenURI}.
65+ function tokenURI (uint256 tokenId ) public view virtual override returns (string memory ) {
66+ _requireOwned (tokenId);
67+
68+ string memory _tokenURI = _tokenURIs[tokenId];
69+
70+ // If there is a custom URI for this token, return it
71+ if (bytes (_tokenURI).length > 0 ) {
72+ return _tokenURI;
73+ }
74+
75+ // Otherwise, fall back to the default behavior
76+ return super .tokenURI (tokenId);
77+ }
78+
79+ /// @dev Sets the token URI for a specific token
80+ /// @param tokenId Token ID to set URI for
81+ /// @param tokenURI_ URI to set
82+ function _setTokenURI (uint256 tokenId , string memory tokenURI_ ) internal {
83+ _tokenURIs[tokenId] = tokenURI_;
84+ }
85+ }
0 commit comments