-
Notifications
You must be signed in to change notification settings - Fork 43
/
ImplementsInterface.sol
48 lines (39 loc) · 1.76 KB
/
ImplementsInterface.sol
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
pragma solidity ^0.5.0;
library ImplementsInterface {
bytes4 constant InvalidID = 0xffffffff;
bytes4 constant ERC165ID = 0x01ffc9a7;
function implementsMethod(address _contract, bytes4 _interfaceId) internal view returns (bool) {
(uint256 success, uint256 result) = _noThrowImplements(_contract, ERC165ID);
if ((success==0)||(result==0)) {
return false;
}
(success, result) = _noThrowImplements(_contract, InvalidID);
if ((success==0)||(result!=0)) {
return false;
}
(success, result) = _noThrowImplements(_contract, _interfaceId);
if ((success==1)&&(result==1)) {
return true;
}
return false;
}
function _noThrowImplements(
address _contract,
bytes4 _interfaceId
) private view returns (uint256 success, uint256 result) {
bytes4 erc165ID = ERC165ID;
assembly {
let x := mload(0x40) // Find empty storage location using "free memory pointer"
mstore(x, erc165ID) // Place signature at begining of empty storage
mstore(add(x, 0x04), _interfaceId) // Place first argument directly next to signature
success := staticcall(
30000, // 30k gas
_contract, // To addr
x, // Inputs are stored at location x
0x24, // Inputs are 32 bytes long
x, // Store output over input (saves space)
0x20) // Outputs are 32 bytes long
result := mload(x) // Load the result
}
}
}