@@ -69,9 +69,6 @@ abstract contract ERC404NullOwnerCappedUpgradeable is
6969 /// keccak256(abi.encode(uint256(keccak256("ethscriptions.storage.ERC404NullOwnerCapped")) - 1)) & ~bytes32(uint256(0xff))
7070 bytes32 private constant STORAGE_LOCATION = 0x8a0c9d8e5f7b3a2c1d4e6f8a9b7c5d3e2f1a4b6c8d9e7f5a3b2c1d4e6f8a9b00 ;
7171
72- /// @dev Constant for token id encoding
73- uint256 public constant ID_ENCODING_PREFIX = 1 << 255 ;
74-
7572 // =============================================================
7673 // EVENTS
7774 // =============================================================
@@ -127,14 +124,9 @@ abstract contract ERC404NullOwnerCappedUpgradeable is
127124 ) internal onlyInitializing {
128125 TokenStorage storage $ = _getS ();
129126
130- if (cap_ == 0 || cap_ > ID_ENCODING_PREFIX - 1 ) {
131- revert ERC20InvalidCap (cap_);
132- }
133-
127+ if (cap_ == 0 ) revert ERC20InvalidCap (cap_);
134128 uint256 base = 10 ** decimals ();
135- if (units_ == 0 || units_ % base != 0 ) {
136- revert InvalidUnits (units_);
137- }
129+ if (units_ == 0 || units_ % base != 0 ) revert InvalidUnits (units_);
138130
139131 $.name = name_;
140132 $.symbol = symbol_;
@@ -175,6 +167,17 @@ abstract contract ERC404NullOwnerCappedUpgradeable is
175167 TokenStorage storage $ = _getS ();
176168 return $.balances[account];
177169 }
170+
171+ function balanceOf (address owner_ , uint256 id_ )
172+ public
173+ view
174+ returns (uint256 )
175+ {
176+ TokenStorage storage $ = _getS ();
177+ TokenData storage t = $.tokens[id_];
178+ if (! t.exists) return 0 ;
179+ return t.owner == owner_ ? 1 : 0 ;
180+ }
178181
179182 function allowance (address owner , address spender ) public view virtual override (IERC404 , IERC20 ) returns (uint256 ) {
180183 TokenStorage storage $ = _getS ();
@@ -204,13 +207,11 @@ abstract contract ERC404NullOwnerCappedUpgradeable is
204207 }
205208
206209 function ownerOf (uint256 id_ ) public view virtual override (IERC404 ) returns (address ) {
210+ _validateTokenId (id_);
207211 TokenStorage storage $ = _getS ();
208- uint256 tokenId = _normalizeTokenId (id_);
209- TokenData storage t = $.tokens[tokenId];
212+ TokenData storage t = $.tokens[id_];
210213
211- if (! t.exists) {
212- revert NotFound ();
213- }
214+ if (! t.exists) revert NotFound ();
214215
215216 return t.owner;
216217 }
@@ -221,14 +222,11 @@ abstract contract ERC404NullOwnerCappedUpgradeable is
221222 }
222223
223224 function getApproved (uint256 id_ ) public view virtual returns (address ) {
225+ _validateTokenId (id_);
224226 TokenStorage storage $ = _getS ();
225- uint256 tokenId = _normalizeTokenId (id_ );
227+ if ( ! $.tokens[id_].exists) revert NotFound ( );
226228
227- if (! $.tokens[tokenId].exists) {
228- revert NotFound ();
229- }
230-
231- return $.getApproved[tokenId];
229+ return $.getApproved[id_];
232230 }
233231
234232 function isApprovedForAll (address owner_ , address operator_ ) public view virtual override (IERC404 ) returns (bool ) {
@@ -352,9 +350,6 @@ abstract contract ERC404NullOwnerCappedUpgradeable is
352350 if (newSupply > $.cap) {
353351 revert ERC20ExceededCap (newSupply, $.cap);
354352 }
355- if (newSupply > ID_ENCODING_PREFIX) {
356- revert MintLimitReached ();
357- }
358353 $.totalSupply = newSupply;
359354 } else {
360355 // Transfer
@@ -371,29 +366,25 @@ abstract contract ERC404NullOwnerCappedUpgradeable is
371366 $.balances[to_] += value_;
372367 }
373368
374- emit ERC20Transfer (from_, to_, value_);
369+ emit Transfer (from_, to_, value_);
370+ // emit ERC20Transfer(from_, to_, value_);
375371 }
376372
377373 /// @notice Transfer an ERC721 token
378374 function _transferERC721 (address from_ , address to_ , uint256 id_ ) internal virtual {
379375 TokenStorage storage $ = _getS ();
380- uint256 tokenId = _normalizeTokenId (id_);
381- TokenData storage t = $.tokens[tokenId];
376+ TokenData storage t = $.tokens[id_];
382377
383- if (! t.exists) {
384- revert NotFound ();
385- }
386- if (from_ != t.owner) {
387- revert Unauthorized ();
388- }
378+ if (! t.exists) revert NotFound ();
379+ if (from_ != t.owner) revert Unauthorized ();
389380
390381 if (from_ != address (0 )) {
391382 // Clear approval
392- delete $.getApproved[tokenId ];
383+ delete $.getApproved[id_ ];
393384
394385 // Remove from sender's owned list
395386 uint256 lastTokenId = $.owned[from_][$.owned[from_].length - 1 ];
396- if (lastTokenId != tokenId ) {
387+ if (lastTokenId != id_ ) {
397388 uint256 updatedIndex = t.index;
398389 $.owned[from_][updatedIndex] = lastTokenId;
399390 $.tokens[lastTokenId].index = uint88 (updatedIndex);
@@ -408,9 +399,9 @@ abstract contract ERC404NullOwnerCappedUpgradeable is
408399 }
409400 t.owner = to_;
410401 t.index = uint88 (newIndex);
411- $.owned[to_].push (tokenId );
402+ $.owned[to_].push (id_ );
412403
413- emit ERC721Transfer (from_, to_, tokenId );
404+ emit ERC721Transfer (from_, to_, id_ );
414405 }
415406
416407 /// @notice Mint ERC20 tokens without triggering NFT creation
@@ -426,24 +417,19 @@ abstract contract ERC404NullOwnerCappedUpgradeable is
426417 if (to_ == address (0 )) {
427418 revert InvalidRecipient ();
428419 }
429- if (nftId_ == 0 || nftId_ >= ID_ENCODING_PREFIX - 1 ) {
430- revert InvalidTokenId ();
431- }
420+ _validateTokenId (nftId_);
432421
433422 TokenStorage storage $ = _getS ();
434423
435- // Add the ID_ENCODING_PREFIX to the provided ID
436- uint256 id = _encodeMintId (nftId_);
437-
438- TokenData storage t = $.tokens[id];
424+ TokenData storage t = $.tokens[nftId_];
439425
440426 // Check if this NFT already exists (including null-owner)
441427 if (t.exists) {
442428 revert AlreadyExists ();
443429 }
444430
445431 t.exists = true ;
446- _transferERC721 (address (0 ), to_, id );
432+ _transferERC721 (address (0 ), to_, nftId_ );
447433
448434 // Increment minted supply counter
449435 $.minted++ ;
@@ -453,37 +439,11 @@ abstract contract ERC404NullOwnerCappedUpgradeable is
453439 // HELPER FUNCTIONS
454440 // =============================================================
455441
456- /// @dev Normalizes caller input into the encoded tokenId form (adds prefix for human mint IDs) .
457- function _normalizeTokenId (uint256 id_ ) internal pure returns ( uint256 tokenId_ ) {
442+ /// @dev Simple tokenId validation: nonzero and not max uint256 .
443+ function _validateTokenId (uint256 id_ ) internal pure {
458444 if (id_ == 0 || id_ == type (uint256 ).max) {
459445 revert InvalidTokenId ();
460446 }
461-
462- tokenId_ = id_ < ID_ENCODING_PREFIX ? _encodeMintId (id_) : id_;
463-
464- if (tokenId_ <= ID_ENCODING_PREFIX || tokenId_ == type (uint256 ).max) {
465- revert InvalidTokenId ();
466- }
467- }
468-
469- /// @dev Encodes a human-friendly mintId into the full tokenId with prefix.
470- function _encodeMintId (uint256 mintId_ ) internal pure returns (uint256 ) {
471- if (mintId_ == 0 || mintId_ >= ID_ENCODING_PREFIX) {
472- revert InvalidTokenId ();
473- }
474- uint256 tokenId = ID_ENCODING_PREFIX + mintId_;
475- if (tokenId == type (uint256 ).max) {
476- revert InvalidTokenId ();
477- }
478- return tokenId;
479- }
480-
481- /// @dev Decodes an encoded tokenId back to the human-friendly mintId.
482- function _decodeTokenId (uint256 tokenId_ ) internal pure returns (uint256 ) {
483- if (tokenId_ <= ID_ENCODING_PREFIX || tokenId_ == type (uint256 ).max) {
484- revert InvalidTokenId ();
485- }
486- return tokenId_ - ID_ENCODING_PREFIX;
487447 }
488448
489449 // =============================================================
0 commit comments