Adopt new Solidity features interfaceId, try/catch, keccak constants (#2487)
* Clean code - using type().interfaceId to improve readeability of ERC165 registration - hardcoding some keccak256 that are otherwise computed at construction. * hardcode keccak256 result * Improve code readeability using try/catch * Remove hardcoded hash tests show that solc 0.8.0 does the optimization as expected * Use try/catch to improve readability * ERC165Checker: Do not revert when returndata is empty + new test * Address PR comments * improve testing of ERC721Receiver errors * put back comment about invalid interface id * coverage does not support 0.8.1. Reverting back to 0.8.0 * bubble all data with length > 0 if onERC721Receive fails. * Fix test: revert without message trigger is bubble with the default message * using enum object to improve readability
This commit is contained in:
@ -11,11 +11,6 @@ import "./IERC165.sol";
|
||||
* their support of an interface.
|
||||
*/
|
||||
abstract contract ERC165 is IERC165 {
|
||||
/*
|
||||
* bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7
|
||||
*/
|
||||
bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
|
||||
|
||||
/**
|
||||
* @dev Mapping of interface ids to whether or not it's supported.
|
||||
*/
|
||||
@ -24,7 +19,7 @@ abstract contract ERC165 is IERC165 {
|
||||
constructor () {
|
||||
// Derived contracts need only register support for their own interfaces,
|
||||
// we register support for ERC165 itself here
|
||||
_registerInterface(_INTERFACE_ID_ERC165);
|
||||
_registerInterface(type(IERC165).interfaceId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
import "./IERC165.sol";
|
||||
|
||||
/**
|
||||
* @dev Library used to query support of an interface declared via {IERC165}.
|
||||
*
|
||||
@ -13,18 +15,13 @@ library ERC165Checker {
|
||||
// As per the EIP-165 spec, no interface should ever match 0xffffffff
|
||||
bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;
|
||||
|
||||
/*
|
||||
* bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7
|
||||
*/
|
||||
bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
|
||||
|
||||
/**
|
||||
* @dev Returns true if `account` supports the {IERC165} interface,
|
||||
*/
|
||||
function supportsERC165(address account) internal view returns (bool) {
|
||||
// Any contract that implements ERC165 must explicitly indicate support of
|
||||
// InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid
|
||||
return _supportsERC165Interface(account, _INTERFACE_ID_ERC165) &&
|
||||
return _supportsERC165Interface(account, type(IERC165).interfaceId) &&
|
||||
!_supportsERC165Interface(account, _INTERFACE_ID_INVALID);
|
||||
}
|
||||
|
||||
@ -101,29 +98,9 @@ library ERC165Checker {
|
||||
* Interface identification is specified in ERC-165.
|
||||
*/
|
||||
function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) {
|
||||
// success determines whether the staticcall succeeded and result determines
|
||||
// whether the contract at account indicates support of _interfaceId
|
||||
(bool success, bool result) = _callERC165SupportsInterface(account, interfaceId);
|
||||
|
||||
return (success && result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Calls the function with selector 0x01ffc9a7 (ERC165) and suppresses throw
|
||||
* @param account The address of the contract to query for support of an interface
|
||||
* @param interfaceId The interface identifier, as specified in ERC-165
|
||||
* @return success true if the STATICCALL succeeded, false otherwise
|
||||
* @return result true if the STATICCALL succeeded and the contract at account
|
||||
* indicates support of the interface with identifier interfaceId, false otherwise
|
||||
*/
|
||||
function _callERC165SupportsInterface(address account, bytes4 interfaceId)
|
||||
private
|
||||
view
|
||||
returns (bool, bool)
|
||||
{
|
||||
bytes memory encodedParams = abi.encodeWithSelector(_INTERFACE_ID_ERC165, interfaceId);
|
||||
bytes memory encodedParams = abi.encodeWithSelector(IERC165(account).supportsInterface.selector, interfaceId);
|
||||
(bool success, bytes memory result) = account.staticcall{ gas: 30000 }(encodedParams);
|
||||
if (result.length < 32) return (false, false);
|
||||
return (success, abi.decode(result, (bool)));
|
||||
if (result.length < 32) return false;
|
||||
return success && abi.decode(result, (bool));
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,7 +13,7 @@ import "./IERC1820Implementer.sol";
|
||||
* registration to be complete.
|
||||
*/
|
||||
contract ERC1820Implementer is IERC1820Implementer {
|
||||
bytes32 constant private _ERC1820_ACCEPT_MAGIC = keccak256(abi.encodePacked("ERC1820_ACCEPT_MAGIC"));
|
||||
bytes32 private constant _ERC1820_ACCEPT_MAGIC = keccak256("ERC1820_ACCEPT_MAGIC");
|
||||
|
||||
mapping(bytes32 => mapping(address => bool)) private _supportedInterfaces;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user