forked from Perfect-Abstractions/Compose
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathERC721DataFacet.sol
More file actions
104 lines (93 loc) · 3.46 KB
/
ERC721DataFacet.sol
File metadata and controls
104 lines (93 loc) · 3.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.30;
/* Compose
* https://compose.diamonds
*/
/**
* @title ERC-721 Data Facet
*/
contract ERC721DataFacet {
/**
* @notice Error indicating the queried owner address is invalid (zero address).
*/
error ERC721InvalidOwner(address _owner);
/**
* @notice Error indicating that the queried token does not exist.
*/
error ERC721NonexistentToken(uint256 _tokenId);
bytes32 constant STORAGE_POSITION = keccak256("erc721");
/**
* @custom:storage-location erc8042:erc721
*/
struct ERC721Storage {
mapping(uint256 tokenId => address owner) ownerOf;
mapping(address owner => uint256 balance) balanceOf;
mapping(address owner => mapping(address operator => bool approved)) isApprovedForAll;
mapping(uint256 tokenId => address approved) approved;
}
/**
* @notice Returns a pointer to the ERC-721 storage struct.
* @dev Uses inline assembly to access the storage slot defined by STORAGE_POSITION.
* @return s The ERC721Storage struct in storage.
*/
function getStorage() internal pure returns (ERC721Storage storage s) {
bytes32 position = STORAGE_POSITION;
assembly {
s.slot := position
}
}
/**
* @notice Returns the number of tokens owned by a given address.
* @param _owner The address to query the balance of.
* @return The balance (number of tokens) owned by `_owner`.
*/
function balanceOf(address _owner) external view returns (uint256) {
if (_owner == address(0)) {
revert ERC721InvalidOwner(_owner);
}
return getStorage().balanceOf[_owner];
}
/**
* @notice Returns the owner of a given token ID.
* @param _tokenId The token ID to query.
* @return The address of the token owner.
*/
function ownerOf(uint256 _tokenId) public view returns (address) {
address owner = getStorage().ownerOf[_tokenId];
if (owner == address(0)) {
revert ERC721NonexistentToken(_tokenId);
}
return owner;
}
/**
* @notice Returns the approved address for a given token ID.
* @param _tokenId The token ID to query the approval of.
* @return The approved address for the token.
*/
function getApproved(uint256 _tokenId) external view returns (address) {
address owner = getStorage().ownerOf[_tokenId];
if (owner == address(0)) {
revert ERC721NonexistentToken(_tokenId);
}
return getStorage().approved[_tokenId];
}
/**
* @notice Returns true if an operator is approved to manage all of an owner's assets.
* @param _owner The token owner.
* @param _operator The operator address.
* @return True if the operator is approved for all tokens of the owner.
*/
function isApprovedForAll(address _owner, address _operator) external view returns (bool) {
return getStorage().isApprovedForAll[_owner][_operator];
}
/**
* @notice Exports the function selectors of the ERC721DataFacet
* @dev This function is use as a selector discovery mechanism for diamonds
* @return selectors The exported function selectors of the ERC721DataFacet
*/
function exportSelectors() external pure returns (bytes memory) {
return bytes.concat(
this.balanceOf.selector, this.ownerOf.selector, this.getApproved.selector, this.isApprovedForAll.selector
);
}
}