1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^ 0.8.18 ;
3
+
4
+ import "@openzeppelin/contracts/utils/Address.sol " ;
5
+ import "@openzeppelin/contracts/utils/Context.sol " ;
6
+ import "@openzeppelin/contracts/utils/Strings.sol " ;
7
+ import "@openzeppelin/contracts/utils/introspection/ERC165.sol " ;
8
+
9
+ interface IERC1151Receiver {
10
+ function onERC1151Received (address operator , address from , uint256 tokenId , bytes calldata data ) external returns (bytes4 );
11
+ }
12
+
13
+ contract MyERC1151 is Context , ERC165 {
14
+ using Address for address ;
15
+ using Strings for uint256 ;
16
+
17
+ string private _name;
18
+ string private _symbol;
19
+ string private _baseUri;
20
+
21
+ mapping (uint256 => address ) private _nftOwners;
22
+ mapping (address => uint256 ) private _ownerToNFTCount;
23
+ mapping (uint256 => address ) private _nftApprovals;
24
+ mapping (uint256 => uint256 ) private _nftBalances;
25
+ mapping (uint256 => string ) private _nftData;
26
+ mapping (address => mapping (address => bool )) private _operatorApprovals;
27
+
28
+ event Transfer (address indexed from , address indexed to , uint256 indexed tokenId );
29
+ event Approval (address indexed owner , address indexed approved , uint256 indexed tokenId );
30
+ event ApprovalForAll (address indexed owner , address indexed operator , bool approved );
31
+
32
+ constructor (
33
+ string memory name_ ,
34
+ string memory symbol_ ,
35
+ string memory baseUri_
36
+ ) {
37
+ _name = name_;
38
+ _symbol = symbol_;
39
+ _baseUri = baseUri_;
40
+ }
41
+
42
+ function balanceOf (address owner ) public view virtual returns (uint256 ) {
43
+ require (owner != address (0 ), "ERC1151: balance query for the zero address " );
44
+ return _ownerToNFTCount[owner];
45
+ }
46
+
47
+ function ownerOf (uint256 tokenId ) public view virtual returns (address ) {
48
+ address owner = _nftOwners[tokenId];
49
+ require (owner != address (0 ), "ERC1151: owner query for nonexistent token " );
50
+ return owner;
51
+ }
52
+
53
+ function name () public view virtual returns (string memory ) {
54
+ return _name;
55
+ }
56
+
57
+ function symbol () public view virtual returns (string memory ) {
58
+ return _symbol;
59
+ }
60
+
61
+ function tokenURI (uint256 tokenId ) public view virtual returns (string memory ) {
62
+ require (_exists (tokenId), "ERC1151: URI query for nonexistent token " );
63
+ string memory baseURI = _baseURI ();
64
+ return bytes (baseURI).length > 0 ? string (abi.encodePacked (baseURI, tokenId.toString ())) : "" ;
65
+ }
66
+
67
+ function _baseURI () internal view virtual returns (string memory ) {
68
+ return _baseUri;
69
+ }
70
+
71
+ function approve (address to , uint256 tokenId ) public virtual {
72
+ address owner = ownerOf (tokenId);
73
+ require (to != owner, "ERC1151: approval to current owner " );
74
+ require (_msgSender () == owner || isApprovedForAll (owner, _msgSender ()), "ERC1151: approve caller is not owner nor approved for all " );
75
+ _approve (to, tokenId);
76
+ }
77
+
78
+ function getApproved (uint256 tokenId ) public view virtual returns (address ) {
79
+ require (_exists (tokenId), "ERC1151: approved query for nonexistent token " );
80
+ return _nftApprovals[tokenId];
81
+ }
82
+
83
+ function setApprovalForAll (address operator , bool approved ) public virtual {
84
+ require (operator != _msgSender (), "ERC1151: approve to caller " );
85
+ _operatorApprovals[_msgSender ()][operator] = approved;
86
+ emit ApprovalForAll (_msgSender (), operator, approved);
87
+ }
88
+
89
+ function isApprovedForAll (address owner , address operator ) public view virtual returns (bool ) {
90
+ return _operatorApprovals[owner][operator];
91
+ }
92
+
93
+ function transferFrom (address from , address to , uint256 tokenId ) public virtual {
94
+ require (_isApprovedOrOwner (_msgSender (), tokenId), "ERC1151: transfer caller is not owner nor approved " );
95
+ _transfer (from, to, tokenId);
96
+ }
97
+
98
+ function safeTransferFrom (address from , address to , uint256 tokenId ) public virtual {
99
+ safeTransferFrom (from, to, tokenId, "" );
100
+ }
101
+
102
+ function safeTransferFrom (address from , address to , uint256 tokenId , bytes memory _data ) public virtual {
103
+ require (_isApprovedOrOwner (_msgSender (), tokenId), "ERC1151: transfer caller is not owner nor approved " );
104
+ _safeTransfer (from, to, tokenId, _data);
105
+ }
106
+
107
+ function _safeTransfer (address from , address to , uint256 tokenId , bytes memory _data ) internal virtual {
108
+ _transfer (from, to, tokenId);
109
+ require (_checkOnERC1151Received (from, to, tokenId, _data), "ERC1151: transfer to non-ERC1151Receiver implementer " );
110
+ }
111
+
112
+ function _exists (uint256 tokenId ) internal view virtual returns (bool ) {
113
+ return _nftOwners[tokenId] != address (0 );
114
+ }
115
+
116
+ function _isApprovedOrOwner (address spender , uint256 tokenId ) internal view virtual returns (bool ) {
117
+ require (_exists (tokenId), "ERC1151: operator query for nonexistent token " );
118
+ address owner = ownerOf (tokenId);
119
+ return (spender == owner || getApproved (tokenId) == spender || isApprovedForAll (owner, spender));
120
+ }
121
+
122
+ function _safeMint (address to , uint256 tokenId ) internal virtual {
123
+ _safeMint (to, tokenId, "" );
124
+ }
125
+
126
+ function _safeMint (address to , uint256 tokenId , bytes memory _data ) internal virtual {
127
+ _mint (to, tokenId);
128
+ require (_checkOnERC1151Received (address (0 ), to, tokenId, _data), "ERC1151: transfer to non-ERC1151Receiver implementer " );
129
+ }
130
+
131
+ function _mint (address to , uint256 tokenId ) internal virtual {
132
+ require (to != address (0 ), "ERC1151: mint to the zero address " );
133
+ require (! _exists (tokenId), "ERC1151: token already minted " );
134
+
135
+ _beforeTokenTransfer (address (0 ), to, tokenId);
136
+
137
+ _nftOwners[tokenId] = to;
138
+ _ownerToNFTCount[to] += 1 ;
139
+
140
+ emit Transfer (address (0 ), to, tokenId);
141
+ }
142
+
143
+ function _burn (uint256 tokenId ) internal virtual {
144
+ address owner = ownerOf (tokenId);
145
+
146
+ _beforeTokenTransfer (owner, address (0 ), tokenId);
147
+
148
+ // Clear approvals
149
+ _approve (address (0 ), tokenId);
150
+
151
+ _ownerToNFTCount[owner] -= 1 ;
152
+ delete _nftOwners[tokenId];
153
+
154
+ emit Transfer (owner, address (0 ), tokenId);
155
+ }
156
+
157
+ function _transfer (address from , address to , uint256 tokenId ) internal virtual {
158
+ require (ownerOf (tokenId) == from, "ERC1151: transfer of token that is not own " );
159
+ require (to != address (0 ), "ERC1151: transfer to the zero address " );
160
+
161
+ _beforeTokenTransfer (from, to, tokenId);
162
+
163
+ // Clear approvals from the previous owner
164
+ _approve (address (0 ), tokenId);
165
+
166
+ _ownerToNFTCount[from] -= 1 ;
167
+ _ownerToNFTCount[to] += 1 ;
168
+ _nftOwners[tokenId] = to;
169
+
170
+ emit Transfer (from, to, tokenId);
171
+ }
172
+
173
+ function _approve (address to , uint256 tokenId ) internal virtual {
174
+ _nftApprovals[tokenId] = to;
175
+ emit Approval (ownerOf (tokenId), to, tokenId);
176
+ }
177
+
178
+ function _checkOnERC1151Received (address from , address to , uint256 tokenId , bytes memory _data ) private returns (bool ) {
179
+ if (to.code.length > 0 ) {
180
+ try IERC1151Receiver (to).onERC1151Received (_msgSender (), from, tokenId, _data) returns (bytes4 retval ) {
181
+ return retval == IERC1151Receiver .onERC1151Received.selector ;
182
+ } catch (bytes memory reason ) {
183
+ if (reason.length == 0 ) {
184
+ revert ("ERC1151: transfer to non-ERC1151Receiver implementer " );
185
+ } else {
186
+ assembly {
187
+ revert (add (32 , reason), mload (reason))
188
+ }
189
+ }
190
+ }
191
+ } else {
192
+ return true ;
193
+ }
194
+ }
195
+
196
+ function _beforeTokenTransfer (address from , address to , uint256 tokenId ) internal virtual {}
197
+ }
0 commit comments