Draft EIP 1820 (#1677)
* Add barebones EIP1820 support. * Update openzeppelin-test-helpers dependency to have ERC1820 support. * Add tests for ERC1820. * Improve inline documentation. * Add changelog entry. * Update test-helpers, refactor tests to use new helpers. * Rename ERC1820 to ERC1820Implementer. * Improve implementer docstring. * Remove _implementsInterfaceForAddress. * update openzeppelin-test-helpers to 0.2.0 * Update contracts/drafts/ERC1820Implementer.sol Co-Authored-By: nventuro <nicolas.venturo@gmail.com> * Fix how solidity coverage is run to allow for free events. * Fix coverage testing script.
This commit is contained in:
24
contracts/drafts/ERC1820Implementer.sol
Normal file
24
contracts/drafts/ERC1820Implementer.sol
Normal file
@ -0,0 +1,24 @@
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "./IERC1820Implementer.sol";
|
||||
|
||||
/**
|
||||
* @dev ERC1820Implementer allows your contract to implement an interface for another account in the sense of ERC1820.
|
||||
* That account or one of its ERC1820 managers can register the implementer in the ERC1820 registry, but the registry
|
||||
* will first check with the implementer if it agrees to it, and only allow it if it does. Using the internal
|
||||
* function _registerInterfaceForAddress provided by this contract, you are expressing this agreement,
|
||||
* and you will be able to register the contract as an implementer in the registry for that account.
|
||||
*/
|
||||
contract ERC1820Implementer is IERC1820Implementer {
|
||||
bytes32 constant private ERC1820_ACCEPT_MAGIC = keccak256(abi.encodePacked("ERC1820_ACCEPT_MAGIC"));
|
||||
|
||||
mapping(bytes32 => mapping(address => bool)) private _supportedInterfaces;
|
||||
|
||||
function canImplementInterfaceForAddress(bytes32 interfaceHash, address account) external view returns (bytes32) {
|
||||
return _supportedInterfaces[interfaceHash][account] ? ERC1820_ACCEPT_MAGIC : bytes32(0x00);
|
||||
}
|
||||
|
||||
function _registerInterfaceForAddress(bytes32 interfaceHash, address account) internal {
|
||||
_supportedInterfaces[interfaceHash][account] = true;
|
||||
}
|
||||
}
|
||||
17
contracts/drafts/IERC1820Implementer.sol
Normal file
17
contracts/drafts/IERC1820Implementer.sol
Normal file
@ -0,0 +1,17 @@
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
/**
|
||||
* @title IERC1820Implementer
|
||||
* Interface for contracts that will be registered as implementers in the ERC1820 registry.
|
||||
* @notice For more details, see https://eips.ethereum.org/EIPS/eip-1820
|
||||
*/
|
||||
interface IERC1820Implementer {
|
||||
/**
|
||||
* @notice Indicates whether the contract implements the interface `interfaceHash` for the address `account` or
|
||||
* not.
|
||||
* @param interfaceHash keccak256 hash of the name of the interface
|
||||
* @param account Address for which the contract will implement the interface
|
||||
* @return ERC1820_ACCEPT_MAGIC only if the contract implements `interfaceHash` for the address `account`.
|
||||
*/
|
||||
function canImplementInterfaceForAddress(bytes32 interfaceHash, address account) external view returns (bytes32);
|
||||
}
|
||||
90
contracts/drafts/IERC1820Registry.sol
Normal file
90
contracts/drafts/IERC1820Registry.sol
Normal file
@ -0,0 +1,90 @@
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
/**
|
||||
* @title ERC1820 Pseudo-introspection Registry Contract
|
||||
* @author Jordi Baylina and Jacques Dafflon
|
||||
* @notice For more details, see https://eips.ethereum.org/EIPS/eip-1820
|
||||
*/
|
||||
interface IERC1820Registry {
|
||||
/**
|
||||
* @notice Sets the contract which implements a specific interface for an address.
|
||||
* Only the manager defined for that address can set it.
|
||||
* (Each address is the manager for itself until it sets a new manager.)
|
||||
* @param account Address for which to set the interface.
|
||||
* (If 'account' is the zero address then 'msg.sender' is assumed.)
|
||||
* @param interfaceHash Keccak256 hash of the name of the interface as a string.
|
||||
* E.g., 'web3.utils.keccak256("ERC777TokensRecipient")' for the 'ERC777TokensRecipient' interface.
|
||||
* @param implementer Contract address implementing `interfaceHash` for `account.address()`.
|
||||
*/
|
||||
function setInterfaceImplementer(address account, bytes32 interfaceHash, address implementer) external;
|
||||
|
||||
/**
|
||||
* @notice Sets `newManager.address()` as manager for `account.address()`.
|
||||
* The new manager will be able to call 'setInterfaceImplementer' for `account.address()`.
|
||||
* @param account Address for which to set the new manager.
|
||||
* @param newManager Address of the new manager for `addr.address()`.
|
||||
* (Pass '0x0' to reset the manager to `account.address()`.)
|
||||
*/
|
||||
function setManager(address account, address newManager) external;
|
||||
|
||||
/**
|
||||
* @notice Updates the cache with whether the contract implements an ERC165 interface or not.
|
||||
* @param account Address of the contract for which to update the cache.
|
||||
* @param interfaceId ERC165 interface for which to update the cache.
|
||||
*/
|
||||
function updateERC165Cache(address account, bytes4 interfaceId) external;
|
||||
|
||||
/**
|
||||
* @notice Get the manager of an address.
|
||||
* @param account Address for which to return the manager.
|
||||
* @return Address of the manager for a given address.
|
||||
*/
|
||||
function getManager(address account) external view returns (address);
|
||||
|
||||
/**
|
||||
* @notice Query if an address implements an interface and through which contract.
|
||||
* @param account Address being queried for the implementer of an interface.
|
||||
* (If 'account' is the zero address then 'msg.sender' is assumed.)
|
||||
* @param interfaceHash Keccak256 hash of the name of the interface as a string.
|
||||
* E.g., 'web3.utils.keccak256("ERC777TokensRecipient")' for the 'ERC777TokensRecipient' interface.
|
||||
* @return The address of the contract which implements the interface `interfaceHash` for `account.address()`
|
||||
* or '0' if `account.address()` did not register an implementer for this interface.
|
||||
*/
|
||||
function getInterfaceImplementer(address account, bytes32 interfaceHash) external view returns (address);
|
||||
|
||||
/**
|
||||
* @notice Checks whether a contract implements an ERC165 interface or not.
|
||||
* If the result is not cached a direct lookup on the contract address is performed.
|
||||
* If the result is not cached or the cached value is out-of-date, the cache MUST be updated manually by calling
|
||||
* 'updateERC165Cache' with the contract address.
|
||||
* @param account Address of the contract to check.
|
||||
* @param interfaceId ERC165 interface to check.
|
||||
* @return True if `account.address()` implements `interfaceId`, false otherwise.
|
||||
*/
|
||||
function implementsERC165Interface(address account, bytes4 interfaceId) external view returns (bool);
|
||||
|
||||
/**
|
||||
* @notice Checks whether a contract implements an ERC165 interface or not without using nor updating the cache.
|
||||
* @param account Address of the contract to check.
|
||||
* @param interfaceId ERC165 interface to check.
|
||||
* @return True if `account.address()` implements `interfaceId`, false otherwise.
|
||||
*/
|
||||
function implementsERC165InterfaceNoCache(address account, bytes4 interfaceId) external view returns (bool);
|
||||
|
||||
/**
|
||||
* @notice Compute the keccak256 hash of an interface given its name.
|
||||
* @param interfaceName Name of the interface.
|
||||
* @return The keccak256 hash of an interface name.
|
||||
*/
|
||||
function interfaceHash(string calldata interfaceName) external pure returns (bytes32);
|
||||
|
||||
/**
|
||||
* @notice Indicates a contract is the `implementer` of `interfaceHash` for `account`.
|
||||
*/
|
||||
event InterfaceImplementerSet(address indexed account, bytes32 indexed interfaceHash, address indexed implementer);
|
||||
|
||||
/**
|
||||
* @notice Indicates `newManager` is the address of the new manager for `account`.
|
||||
*/
|
||||
event ManagerChanged(address indexed account, address indexed newManager);
|
||||
}
|
||||
Reference in New Issue
Block a user