Skip to content

Commit 9612195

Browse files
authored
Merge pull request #284 from solidstate-network/erc721-extension-interfaces
Add `ERC721` and `ERC1155` extension interfaces
2 parents c20183e + e0f50a4 commit 9612195

23 files changed

+203
-73
lines changed
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
pragma solidity ^0.8.20;
4+
5+
import { _IERC1155Metadata } from './_IERC1155Metadata.sol';
6+
7+
interface IERC1155Metadata is _IERC1155Metadata {
8+
/**
9+
* @notice get generated URI for given token
10+
* @return token URI
11+
*/
12+
function uri(uint256 tokenId) external view returns (string memory);
13+
}
+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
pragma solidity ^0.8.20;
4+
5+
import { _IERC721Enumerable } from './_IERC721Enumerable.sol';
6+
7+
interface IERC721Enumerable is _IERC721Enumerable {
8+
/**
9+
* @notice get total token supply
10+
* @return total supply
11+
*/
12+
function totalSupply() external view returns (uint256);
13+
14+
/**
15+
* @notice get token of given owner at given internal storage index
16+
* @param owner token holder to query
17+
* @param index position in owner's token list to query
18+
* @return tokenId id of retrieved token
19+
*/
20+
function tokenOfOwnerByIndex(
21+
address owner,
22+
uint256 index
23+
) external view returns (uint256 tokenId);
24+
25+
/**
26+
* @notice get token at given internal storage index
27+
* @param index position in global token list to query
28+
* @return tokenId id of retrieved token
29+
*/
30+
function tokenByIndex(
31+
uint256 index
32+
) external view returns (uint256 tokenId);
33+
}
+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
pragma solidity ^0.8.20;
4+
5+
import { _IERC721Metadata } from './_IERC721Metadata.sol';
6+
7+
interface IERC721Metadata is _IERC721Metadata {
8+
/**
9+
* @notice get token name
10+
* @return token name
11+
*/
12+
function name() external view returns (string memory);
13+
14+
/**
15+
* @notice get token symbol
16+
* @return token symbol
17+
*/
18+
function symbol() external view returns (string memory);
19+
20+
/**
21+
* @notice get generated URI for given token
22+
* @return token URI
23+
*/
24+
function tokenURI(uint256 tokenId) external view returns (string memory);
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
pragma solidity ^0.8.20;
4+
5+
interface _IERC1155Metadata {
6+
event URI(string value, uint256 indexed tokenId);
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
pragma solidity ^0.8.20;
4+
5+
interface _IERC721Enumerable {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
pragma solidity ^0.8.20;
4+
5+
interface _IERC721Metadata {}

contracts/token/common/royalty/NFTRoyalty.sol

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@
22

33
pragma solidity ^0.8.20;
44

5+
import { IERC2981 } from '../../../interfaces/IERC2981.sol';
56
import { Introspectable } from '../../../introspection/Introspectable.sol';
67
import { INFTRoyalty } from './INFTRoyalty.sol';
7-
import { ERC2981Storage } from '../../../storage/ERC2981Storage.sol';
88
import { _NFTRoyalty } from './_NFTRoyalty.sol';
99

1010
/**
1111
* @title NFTRoyalty implementation
1212
*/
1313
abstract contract NFTRoyalty is INFTRoyalty, _NFTRoyalty, Introspectable {
1414
/**
15-
* @notice inheritdoc INFTRoyalty
15+
* @inheritdoc IERC2981
1616
*/
1717
function royaltyInfo(
1818
uint256 tokenId,

contracts/token/multi/metadata/IMultiTokenMetadata.sol

+2-7
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,10 @@
22

33
pragma solidity ^0.8.20;
44

5+
import { IERC1155Metadata } from '../../../interfaces/IERC1155Metadata.sol';
56
import { _IMultiTokenMetadata } from './_IMultiTokenMetadata.sol';
67

78
/**
89
* @title MultiTokenMetadata interface
910
*/
10-
interface IMultiTokenMetadata is _IMultiTokenMetadata {
11-
/**
12-
* @notice get generated URI for given token
13-
* @return token URI
14-
*/
15-
function uri(uint256 tokenId) external view returns (string memory);
16-
}
11+
interface IMultiTokenMetadata is _IMultiTokenMetadata, IERC1155Metadata {}

contracts/token/multi/metadata/MultiTokenMetadata.sol

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
pragma solidity ^0.8.20;
44

5+
import { IERC1155Metadata } from '../../../interfaces/IERC1155Metadata.sol';
56
import { IMultiTokenMetadata } from './IMultiTokenMetadata.sol';
67
import { _MultiTokenMetadata } from './_MultiTokenMetadata.sol';
78

@@ -13,7 +14,7 @@ abstract contract MultiTokenMetadata is
1314
_MultiTokenMetadata
1415
{
1516
/**
16-
* @notice inheritdoc IMultiTokenMetadata
17+
* @inheritdoc IERC1155Metadata
1718
*/
1819
function uri(uint256 tokenId) external view returns (string memory) {
1920
return _uri(tokenId);

contracts/token/multi/metadata/_IMultiTokenMetadata.sol

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
pragma solidity ^0.8.20;
44

5+
import { _IERC1155Metadata } from '../../../interfaces/_IERC1155Metadata.sol';
6+
57
/**
68
* @title Partial MultiTokenMetadata interface needed by internal functions
79
*/
8-
interface _IMultiTokenMetadata {
9-
event URI(string value, uint256 indexed tokenId);
10-
}
10+
interface _IMultiTokenMetadata is _IERC1155Metadata {}

contracts/token/multi/metadata/_MultiTokenMetadata.sol

+15-1
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,26 @@ abstract contract _MultiTokenMetadata is _IMultiTokenMetadata {
2525
if (bytes(baseURI).length == 0) {
2626
return tokenURI;
2727
} else if (bytes(tokenURI).length == 0) {
28-
return string(abi.encodePacked(baseURI, tokenId.toDecString()));
28+
return
29+
string(
30+
abi.encodePacked(baseURI, _generateDefaultTokenURI(tokenId))
31+
);
2932
} else {
3033
return string(abi.encodePacked(baseURI, tokenURI));
3134
}
3235
}
3336

37+
/**
38+
* @notice generate URI component for token id
39+
* @dev padded hex string is used to match https://eips.ethereum.org/EIPS/eip-1155#metadata
40+
* @return tokenURI token URI component
41+
*/
42+
function _generateDefaultTokenURI(
43+
uint256 tokenId
44+
) internal view virtual returns (string memory tokenURI) {
45+
tokenURI = tokenId.toString(16, 64);
46+
}
47+
3448
/**
3549
* @notice set base metadata URI
3650
* @dev base URI is a non-standard feature adapted from the ERC721 specification

contracts/token/non_fungible/enumerable/INonFungibleTokenEnumerable.sol

+4-28
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,12 @@
22

33
pragma solidity ^0.8.20;
44

5+
import { IERC721Enumerable } from '../../../interfaces/IERC721Enumerable.sol';
56
import { INonFungibleToken } from '../INonFungibleToken.sol';
67
import { _INonFungibleTokenEnumerable } from './_NonFungibleTokenEnumerable.sol';
78

89
interface INonFungibleTokenEnumerable is
910
_INonFungibleTokenEnumerable,
10-
INonFungibleToken
11-
{
12-
/**
13-
* @notice get total token supply
14-
* @return total supply
15-
*/
16-
function totalSupply() external view returns (uint256);
17-
18-
/**
19-
* @notice get token of given owner at given internal storage index
20-
* @param owner token holder to query
21-
* @param index position in owner's token list to query
22-
* @return tokenId id of retrieved token
23-
*/
24-
function tokenOfOwnerByIndex(
25-
address owner,
26-
uint256 index
27-
) external view returns (uint256 tokenId);
28-
29-
/**
30-
* @notice get token at given internal storage index
31-
* @param index position in global token list to query
32-
* @return tokenId id of retrieved token
33-
*/
34-
function tokenByIndex(
35-
uint256 index
36-
) external view returns (uint256 tokenId);
37-
}
11+
INonFungibleToken,
12+
IERC721Enumerable
13+
{}

contracts/token/non_fungible/enumerable/NonFungibleTokenEnumerable.sol

+4-3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ pragma solidity ^0.8.20;
55
import { EnumerableMap } from '../../../data/EnumerableMap.sol';
66
import { EnumerableSet } from '../../../data/EnumerableSet.sol';
77
import { ERC721Storage } from '../../../storage/ERC721Storage.sol';
8+
import { IERC721Enumerable } from '../../../interfaces/IERC721Enumerable.sol';
89
import { NonFungibleToken } from '../NonFungibleToken.sol';
910
import { INonFungibleTokenEnumerable } from './INonFungibleTokenEnumerable.sol';
1011
import { _NonFungibleTokenEnumerable } from './_NonFungibleTokenEnumerable.sol';
@@ -18,14 +19,14 @@ abstract contract NonFungibleTokenEnumerable is
1819
using EnumerableSet for EnumerableSet.UintSet;
1920

2021
/**
21-
* @inheritdoc INonFungibleTokenEnumerable
22+
* @inheritdoc IERC721Enumerable
2223
*/
2324
function totalSupply() external view returns (uint256) {
2425
return _totalSupply();
2526
}
2627

2728
/**
28-
* @inheritdoc INonFungibleTokenEnumerable
29+
* @inheritdoc IERC721Enumerable
2930
*/
3031
function tokenOfOwnerByIndex(
3132
address owner,
@@ -35,7 +36,7 @@ abstract contract NonFungibleTokenEnumerable is
3536
}
3637

3738
/**
38-
* @inheritdoc INonFungibleTokenEnumerable
39+
* @inheritdoc IERC721Enumerable
3940
*/
4041
function tokenByIndex(uint256 index) external view returns (uint256) {
4142
return _tokenByIndex(index);

contracts/token/non_fungible/enumerable/_INonFungibleTokenEnumerable.sol

+5-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
pragma solidity ^0.8.20;
44

5+
import { _IERC721Enumerable } from '../../../interfaces/_IERC721Enumerable.sol';
56
import { _INonFungibleToken } from '../_INonFungibleToken.sol';
67

7-
interface _INonFungibleTokenEnumerable is _INonFungibleToken {}
8+
interface _INonFungibleTokenEnumerable is
9+
_INonFungibleToken,
10+
_IERC721Enumerable
11+
{}

contracts/token/non_fungible/metadata/INonFungibleTokenMetadata.sol

+5-19
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,13 @@
22

33
pragma solidity ^0.8.20;
44

5+
import { IERC721Metadata } from '../../../interfaces/IERC721Metadata.sol';
56
import { _INonFungibleTokenMetadata } from './_INonFungibleTokenMetadata.sol';
67

78
/**
89
* @title NonFungibleTokenMetadata interface
910
*/
10-
interface INonFungibleTokenMetadata is _INonFungibleTokenMetadata {
11-
/**
12-
* @notice get token name
13-
* @return token name
14-
*/
15-
function name() external view returns (string memory);
16-
17-
/**
18-
* @notice get token symbol
19-
* @return token symbol
20-
*/
21-
function symbol() external view returns (string memory);
22-
23-
/**
24-
* @notice get generated URI for given token
25-
* @return token URI
26-
*/
27-
function tokenURI(uint256 tokenId) external view returns (string memory);
28-
}
11+
interface INonFungibleTokenMetadata is
12+
_INonFungibleTokenMetadata,
13+
IERC721Metadata
14+
{}

contracts/token/non_fungible/metadata/NonFungibleTokenMetadata.sol

+4-3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
pragma solidity ^0.8.20;
44

5+
import { IERC721Metadata } from '../../../interfaces/IERC721Metadata.sol';
56
import { _NonFungibleTokenMetadata } from './_NonFungibleTokenMetadata.sol';
67
import { INonFungibleTokenMetadata } from './INonFungibleTokenMetadata.sol';
78

@@ -13,21 +14,21 @@ abstract contract NonFungibleTokenMetadata is
1314
_NonFungibleTokenMetadata
1415
{
1516
/**
16-
* @notice inheritdoc INonFungibleTokenMetadata
17+
* @inheritdoc IERC721Metadata
1718
*/
1819
function name() external view returns (string memory) {
1920
return _name();
2021
}
2122

2223
/**
23-
* @notice inheritdoc INonFungibleTokenMetadata
24+
* @inheritdoc IERC721Metadata
2425
*/
2526
function symbol() external view returns (string memory) {
2627
return _symbol();
2728
}
2829

2930
/**
30-
* @notice inheritdoc INonFungibleTokenMetadata
31+
* @inheritdoc IERC721Metadata
3132
*/
3233
function tokenURI(uint256 tokenId) external view returns (string memory) {
3334
return _tokenURI(tokenId);

contracts/token/non_fungible/metadata/_INonFungibleTokenMetadata.sol

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22

33
pragma solidity ^0.8.20;
44

5-
import { _INonFungibleToken } from '..//_INonFungibleToken.sol';
5+
import { _IERC721Metadata } from '../../../interfaces/_IERC721Metadata.sol';
6+
import { _INonFungibleToken } from '../_INonFungibleToken.sol';
67

78
/**
89
* @title NonFungibleTokenMetadata internal interface
910
*/
10-
interface _INonFungibleTokenMetadata is _INonFungibleToken {
11+
interface _INonFungibleTokenMetadata is _INonFungibleToken, _IERC721Metadata {
1112
error NonFungibleTokenMetadata__NonExistentToken();
1213
}

contracts/token/non_fungible/metadata/_NonFungibleTokenMetadata.sol

+15-1
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,26 @@ abstract contract _NonFungibleTokenMetadata is
5555
if (bytes(baseURI).length == 0) {
5656
return tokenURI;
5757
} else if (bytes(tokenURI).length == 0) {
58-
return string(abi.encodePacked(baseURI, tokenId.toDecString()));
58+
return
59+
string(
60+
abi.encodePacked(baseURI, _generateDefaultTokenURI(tokenId))
61+
);
5962
} else {
6063
return string(abi.encodePacked(baseURI, tokenURI));
6164
}
6265
}
6366

67+
/**
68+
* @notice generate URI component for token id
69+
* @dev padded hex string is used to match https://eips.ethereum.org/EIPS/eip-1155#metadata
70+
* @return tokenURI token URI component
71+
*/
72+
function _generateDefaultTokenURI(
73+
uint256 tokenId
74+
) internal view virtual returns (string memory tokenURI) {
75+
tokenURI = tokenId.toString(16, 64);
76+
}
77+
6478
/**
6579
* @notice set token name
6680
* @param name token name

0 commit comments

Comments
 (0)