forked from Perfect-Abstractions/Compose
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathERC165Facet.sol
More file actions
90 lines (81 loc) · 3.14 KB
/
ERC165Facet.sol
File metadata and controls
90 lines (81 loc) · 3.14 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
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.30;
/* Compose
* https://compose.diamonds
*/
/**
* @title ERC-165 Standard Interface Detection Interface
* @notice Interface for detecting what interfaces a contract implements
* @dev ERC-165 allows contracts to publish their supported interfaces
*/
interface IERC165 {
/**
* @notice Query if a contract implements an interface
* @param _interfaceId The interface identifier, as specified in ERC-165
* @dev Interface identification is specified in ERC-165. This function
* uses less than 30,000 gas.
* @return `true` if the contract implements `_interfaceId` and
* `_interfaceId` is not 0xffffffff, `false` otherwise
*/
function supportsInterface(bytes4 _interfaceId) external view returns (bool);
}
/**
* @title ERC165Facet — ERC-165 Standard Interface Detection Facet
* @notice Facet implementation of ERC-165 for diamond proxy pattern
* @dev Allows querying which interfaces are implemented by the diamond
* Each facet is a standalone source code file following SCOP principles.
*/
contract ERC165Facet {
/**
* @notice Storage slot identifier for ERC-165 interface detection
* @dev Defined using keccak256 hash following ERC-8042 standard
*/
bytes32 constant STORAGE_POSITION = keccak256("erc165");
/**
* @notice ERC-165 storage layout using the ERC-8042 standard
* @custom:storage-location erc8042:erc165
*/
struct ERC165Storage {
/**
* @notice Mapping of interface IDs to whether they are supported
*/
mapping(bytes4 => bool) supportedInterfaces;
}
/**
* @notice Returns a pointer to the ERC-165 storage struct
* @dev Uses inline assembly to bind the storage struct to the fixed storage position
* @return s The ERC-165 storage struct
*/
function getStorage() internal pure returns (ERC165Storage storage s) {
bytes32 position = STORAGE_POSITION;
assembly {
s.slot := position
}
}
/**
* @notice Query if a contract implements an interface
* @param _interfaceId The interface identifier, as specified in ERC-165
* @dev This function checks if the diamond supports the given interface ID
* @return `true` if the contract implements `_interfaceId` and
* `_interfaceId` is not 0xffffffff, `false` otherwise
*/
function supportsInterface(bytes4 _interfaceId) external view returns (bool) {
ERC165Storage storage s = getStorage();
/**
* If the ERC165 interface itself is being queried, return true
* since this facet implements ERC165
*/
if (_interfaceId == type(IERC165).interfaceId) {
return true;
}
return s.supportedInterfaces[_interfaceId];
}
/**
* @notice Exports the function selectors of the ERC165Facet
* @dev This function is use as a selector discovery mechanism for diamonds
* @return selectors The exported function selectors of the ERC165Facet
*/
function exportSelectors() external pure returns (bytes memory) {
return bytes.concat(this.supportsInterface.selector);
}
}