diff --git a/404.html b/404.html new file mode 100644 index 0000000..faf7e23 --- /dev/null +++ b/404.html @@ -0,0 +1,23 @@ +--- +layout: default +--- + + + +
Page not found :(
+The requested page could not be found.
+Please wait...
+Prefixed |
+
|
+
Unprefixed |
+
|
+
See Also |
+Formalized (JSON-Schema) version of this specification: package.spec.json |
+
Jump To |
++ |
Required |
+Yes |
+
Key |
+
|
+
Type |
+String |
+
Allowed Values |
+
|
+
Required |
+Yes |
+
Key |
+
|
+
Type |
+String |
+
Format |
+must match the regular expression |
+
Required |
+No |
+
Key |
+
|
+
Type |
++ |
Required |
+Yes |
+
Key |
+
|
+
Type |
+String |
+
Key |
+
|
+
Type |
+Object (String: String) |
+
Format |
+See Below. |
+
Key |
+
|
+
Type |
+Object (String: Contract Type Object) |
+
Format |
+Keys must be valid Contract Aliases. +Values must conform to the Contract Type Object definition. |
+
Key |
+
|
+
Type |
+Object (String: Object(String: Contract Instance Object)) |
+
Format |
+See Below. |
+
Required |
+No |
+
Key |
+
|
+
Type |
+Object (String: String) |
+
Format |
+Keys must be valid package names matching the regular expression Values must be valid IPFS URIs which resolve to a valid package. |
+
Required |
+Yes |
+
Type |
+Array |
+
Required |
+Yes |
+
Type |
+Integer |
+
Required |
+No |
+
Type |
+String |
+
Format |
+must conform to the Identifier format. |
+
Required |
+Yes |
+
Type |
+Integer |
+
Format |
+See Below. |
+
Required |
+Yes |
+
Type |
+String |
+
Allowed Values |
+
|
+
Required |
+Yes |
+
Type |
+String |
+
Format |
+Determined based on |
+
Required |
+Yes |
+
Type |
+String |
+
Format |
+
|
+
Required |
+No |
+
Type |
+Array |
+
Format |
+All values must be valid Link Reference objects. See also below. |
+
Required |
+No |
+
Type |
+Array |
+
Format |
+All values must be valid Link Value objects. See also below. |
+
Required |
+No |
+
Key |
+
|
+
Type |
+Array (String) |
+
Required |
+No |
+
Key |
+
|
+
Type |
+String |
+
Required |
+No |
+
Key |
+
|
+
Type |
+String |
+
Required |
+No |
+
Key |
+
|
+
Type |
+List of Strings |
+
Key |
+
|
+
Type |
+Object (String: String) |
+
Required |
+If the Contract Name and Contract Alias are not the same. |
+
Type |
+String |
+
Format |
+must be a valid Contract Name. |
+
Required |
+No |
+
Type |
+Object |
+
Format |
+must conform to the Bytecode Object format. |
+
Required |
+No |
+
Type |
+Object |
+
Format |
+must conform to the Bytecode Object format. |
+
Required |
+No |
+
Type |
+List |
+
Format |
+must conform to the Ethereum Contract ABI JSON format. |
+
Required |
+No |
+
Type |
+Object |
+
Format |
++ |
Required |
+No |
+
Type |
+Object |
+
Format |
+must conform to the Compiler Information object format. |
+
Required |
+Yes |
+
Type |
+String |
+
Format |
+See Below. |
+
Required |
+Yes |
+
Type |
+String |
+
Format |
+Hex encoded |
+
Required |
+No |
+
Type |
+String |
+
Format |
+
|
+
Required |
+No |
+
Type |
+String |
+
Format |
+
|
+
Required |
+No |
+
Type |
+Object |
+
Format |
+must conform to the Bytecode Object format. |
+
Required |
+No |
+
Type |
+Object |
+
Format |
+must conform to the Compiler Information Object format. |
+
Required |
+Yes |
+
Key |
+
|
+
Type |
+String |
+
Required |
+Yes |
+
Key |
+
|
+
Type |
+String |
+
Required |
+No |
+
Key |
+
|
+
Type |
+Object |
+
owned |
+A package which contains contracts which are not meant to be used by themselves but rather as base contracts to provide functionality to other contracts through inheritance. |
+
transferable |
+A package which has a single dependency. |
+
standard-token |
+A package which contains a reusable contract. |
+
safe-math-lib |
+A package which contains deployed instance of one of the package contracts. |
+
piper-coin |
+A package which contains a deployed instance of a reusable contract from a dependency. |
+
escrow |
+A package which contains a deployed instance of a local contract which is linked against a deployed instance of a local library. |
+
wallet |
+A package with a deployed instance of a local contract which is linked against a deployed instance of a library from a dependency. |
+
wallet-with-send |
+A package with a deployed instance which links against a deep dependency. |
+
Unlinked Bytecode |
+The hexadecimal representation of a contract’s EVM instructions that contains sections of code that requires linking for the contract to be functional. +The sections of code which are unlinked must be filled in with zero bytes. +Example: |
+
Linked Bytecode |
+The hexadecimal representation of a contract’s EVM instructions which has had all Link References replaced with the desired Link Values. +Example: |
+
|
+Defines the location within the bytecode where the link reference begins. |
+
|
+Defines the length of the reference. |
+
|
+(optional.) A string to identify the reference |
+
Example |
+
|
+
Example |
+
|
+
<domain> ::= <label> | <domain> "." <label> +<label> ::= any valid string label per [UTS46](https://unicode.org/reports/tr46/) ++ +In short, names consist of a series of dot-separated labels. Each label must be a valid normalised label as described in [UTS46](https://unicode.org/reports/tr46/) with the options `transitional=false` and `useSTD3AsciiRules=true`. For Javascript implementations, a [library](https://www.npmjs.com/package/idna-uts46) is available that normalises and checks names. + +Note that while upper and lower case letters are allowed in names, the UTS46 normalisation process case-folds labels before hashing them, so two names with different case but identical spelling will produce the same namehash. + +Labels and domains may be of any length, but for compatibility with legacy DNS, it is recommended that labels be restricted to no more than 64 characters each, and complete ENS names to no more than 255 characters. For the same reason, it is recommended that labels do not start or end with hyphens, or start with digits. + +## namehash algorithm + +Before being used in ENS, names are hashed using the 'namehash' algorithm. This algorithm recursively hashes components of the name, producing a unique, fixed-length string for any valid input domain. The output of namehash is referred to as a 'node'. + +Pseudocode for the namehash algorithm is as follows: + +``` +def namehash(name): + if name == '': + return '\0' * 32 + else: + label, _, remainder = name.partition('.') + return sha3(namehash(remainder) + sha3(label)) +``` + +Informally, the name is split into labels, each label is hashed. Then, starting with the last component, the previous output is concatenated with the label hash and hashed again. The first component is concatenated with 32 '0' bytes. Thus, 'mysite.swarm' is processed as follows: + +``` +node = '\0' * 32 +node = sha3(node + sha3('swarm')) +node = sha3(node + sha3('mysite')) +``` + +Implementations should conform to the following test vectors for namehash: + + namehash('') = 0x0000000000000000000000000000000000000000000000000000000000000000 + namehash('eth') = 0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae + namehash('foo.eth') = 0xde9b09fd7c5f901e23a3f19fecc54828e9c848539801e86591bd9801b019f84f + +## Registry specification + +The ENS registry contract exposes the following functions: + +```solidity +function owner(bytes32 node) constant returns (address); +``` + +Returns the owner (registrar) of the specified node. + +```solidity +function resolver(bytes32 node) constant returns (address); +``` + +Returns the resolver for the specified node. + +```solidity +function ttl(bytes32 node) constant returns (uint64); +``` + +Returns the time-to-live (TTL) of the node; that is, the maximum duration for which a node's information may be cached. + +```solidity +function setOwner(bytes32 node, address owner); +``` + +Transfers ownership of a node to another registrar. This function may only be called by the current owner of `node`. A successful call to this function logs the event `Transfer(bytes32 indexed, address)`. + +```solidity +function setSubnodeOwner(bytes32 node, bytes32 label, address owner); +``` + +Creates a new node, `sha3(node, label)` and sets its owner to `owner`, or updates the node with a new owner if it already exists. This function may only be called by the current owner of `node`. A successful call to this function logs the event `NewOwner(bytes32 indexed, bytes32 indexed, address)`. + +```solidity +function setResolver(bytes32 node, address resolver); +``` + +Sets the resolver address for `node`. This function may only be called by the owner of `node`. A successful call to this function logs the event `NewResolver(bytes32 indexed, address)`. + +```solidity +function setTTL(bytes32 node, uint64 ttl); +``` + +Sets the TTL for a node. A node's TTL applies to the 'owner' and 'resolver' records in the registry, as well as to any information returned by the associated resolver. +## Resolver specification + +Resolvers may implement any subset of the record types specified here. Where a record types specification requires a resolver to provide multiple functions, the resolver MUST implement either all or none of them. Resolvers MUST specify a fallback function that throws. + +Resolvers have one mandatory function: + +```solidity +function supportsInterface(bytes4 interfaceID) constant returns (bool) +``` + +The `supportsInterface` function is documented in [EIP-165](./eip-165.md), and returns true if the resolver implements the interface specified by the provided 4 byte identifier. An interface identifier consists of the XOR of the function signature hashes of the functions provided by that interface; in the degenerate case of single-function interfaces, it is simply equal to the signature hash of that function. If a resolver returns `true` for `supportsInterface()`, it must implement the functions specified in that interface. + +`supportsInterface` must always return true for `0x01ffc9a7`, which is the interface ID of `supportsInterface` itself. + + Currently standardised resolver interfaces are specified in the table below. + +The following interfaces are defined: + +| Interface name | Interface hash | Specification | +| --- | --- | --- | +| `addr` | 0x3b3b57de | [Contract address](#addr) | +| `name` | 0x691f3431 | #181 | +| `ABI` | 0x2203ab56 | #205 | +| `pubkey` | 0xc8690233 | #619 | + +EIPs may define new interfaces to be added to this registry. + +### Contract Address Interface + +Resolvers wishing to support contract address resources must provide the following function: + +```solidity +function addr(bytes32 node) constant returns (address); +``` + +If the resolver supports `addr` lookups but the requested node does not have an addr record, the resolver MUST return the zero address. + +Clients resolving the `addr` record MUST check for a zero return value, and treat this in the same manner as a name that does not have a resolver specified - that is, refuse to send funds to or interact with the address. Failure to do this can result in users accidentally sending funds to the 0 address. + +Changes to an address MUST trigger the following event: + +```solidity +event AddrChanged(bytes32 indexed node, address a); +``` +# Appendix A: Registry Implementation + +```solidity +contract ENS { + struct Record { + address owner; + address resolver; + uint64 ttl; + } + + mapping(bytes32=>Record) records; + + event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner); + event Transfer(bytes32 indexed node, address owner); + event NewResolver(bytes32 indexed node, address resolver); + + modifier only_owner(bytes32 node) { + if(records[node].owner != msg.sender) throw; + _ + } + + function ENS(address owner) { + records[0].owner = owner; + } + + function owner(bytes32 node) constant returns (address) { + return records[node].owner; + } + + function resolver(bytes32 node) constant returns (address) { + return records[node].resolver; + } + + function ttl(bytes32 node) constant returns (uint64) { + return records[node].ttl; + } + + function setOwner(bytes32 node, address owner) only_owner(node) { + Transfer(node, owner); + records[node].owner = owner; + } + + function setSubnodeOwner(bytes32 node, bytes32 label, address owner) only_owner(node) { + var subnode = sha3(node, label); + NewOwner(node, label, owner); + records[subnode].owner = owner; + } + + function setResolver(bytes32 node, address resolver) only_owner(node) { + NewResolver(node, resolver); + records[node].resolver = resolver; + } + + function setTTL(bytes32 node, uint64 ttl) only_owner(node) { + NewTTL(node, ttl); + records[node].ttl = ttl; + } +} +``` +# Appendix B: Sample Resolver Implementations +### Built-in resolver + +The simplest possible resolver is a contract that acts as its own name resolver by implementing the contract address resource profile: + +```solidity +contract DoSomethingUseful { + // Other code + + function addr(bytes32 node) constant returns (address) { + return this; + } + + function supportsInterface(bytes4 interfaceID) constant returns (bool) { + return interfaceID == 0x3b3b57de || interfaceID == 0x01ffc9a7; + } + + function() { + throw; + } +} +``` + +Such a contract can be inserted directly into the ENS registry, eliminating the need for a separate resolver contract in simple use-cases. However, the requirement to 'throw' on unknown function calls may interfere with normal operation of some types of contract. + +### Standalone resolver + +A basic resolver that implements the contract address profile, and allows only its owner to update records: + +```solidity +contract Resolver { + event AddrChanged(bytes32 indexed node, address a); + + address owner; + mapping(bytes32=>address) addresses; + + modifier only_owner() { + if(msg.sender != owner) throw; + _ + } + + function Resolver() { + owner = msg.sender; + } + + function addr(bytes32 node) constant returns(address) { + return addresses[node]; + } + + function setAddr(bytes32 node, address addr) only_owner { + addresses[node] = addr; + AddrChanged(node, addr); + } + + function supportsInterface(bytes4 interfaceID) constant returns (bool) { + return interfaceID == 0x3b3b57de || interfaceID == 0x01ffc9a7; + } + + function() { + throw; + } +} +``` + +After deploying this contract, use it by updating the ENS registry to reference this contract for a name, then calling `setAddr()` with the same node to set the contract address it will resolve to. +### Public resolver + +Similar to the resolver above, this contract only supports the contract address profile, but uses the ENS registry to determine who should be allowed to update entries: + +```solidity +contract PublicResolver { + event AddrChanged(bytes32 indexed node, address a); + event ContentChanged(bytes32 indexed node, bytes32 hash); + + ENS ens; + mapping(bytes32=>address) addresses; + + modifier only_owner(bytes32 node) { + if(ens.owner(node) != msg.sender) throw; + _ + } + + function PublicResolver(address ensAddr) { + ens = ENS(ensAddr); + } + + function addr(bytes32 node) constant returns (address ret) { + ret = addresses[node]; + } + + function setAddr(bytes32 node, address addr) only_owner(node) { + addresses[node] = addr; + AddrChanged(node, addr); + } + + function supportsInterface(bytes4 interfaceID) constant returns (bool) { + return interfaceID == 0x3b3b57de || interfaceID == 0x01ffc9a7; + } + + function() { + throw; + } +} +``` +# Appendix C: Sample Registrar Implementation + +This registrar allows users to register names at no cost if they are the first to request them. + +```solidity +contract FIFSRegistrar { + ENS ens; + bytes32 rootNode; + + function FIFSRegistrar(address ensAddr, bytes32 node) { + ens = ENS(ensAddr); + rootNode = node; + } + + function register(bytes32 subnode, address owner) { + var node = sha3(rootNode, subnode); + var currentOwner = ens.owner(node); + if(currentOwner != 0 && currentOwner != msg.sender) + throw; + + ens.setSubnodeOwner(rootNode, subnode, owner); + } +} +``` diff --git a/EIPS/eip-1380.md b/EIPS/eip-1380.md new file mode 100644 index 0000000..6be8374 --- /dev/null +++ b/EIPS/eip-1380.md @@ -0,0 +1,57 @@ +--- +eip: 1380 +title: Reduced gas cost for call to self +author: Alex Beregszaszi (@axic), Jacques Wagener (@jacqueswww) +discussions-to: https://ethereum-magicians.org/t/eip-1380-reduced-gas-cost-for-call-to-self/1242 +status: Stagnant +type: Standards Track +category: Core +created: 2018-08-31 +requires: 150 +--- + +## Abstract +Reduce the gas cost for call instructions, when the goal is to run a new instance of the currently loaded contract. + +## Motivation +The current gas cost of 700 for all call types (`CALL`, `DELEGATECALL`, `CALLCODE` and `STATICCALL`) does not take into account that a call to a contract itself +does not need to perform additional I/O operations, because the current contract code has already been loaded into memory. + +Reducing the call-to-self gas cost would greatly benefit smart contract languages, such as Solidity and Vyper, who would then be able to utilise `CALL` instead +of `JUMP` opcodes for internal function calls. While languages can already utilise `CALL` for internal function calls, they are discouraged to do so due to the +gas costs associated with it. + +Using `JUMP` comes at a considerable cost in complexity to the implementation of a smart contract language and/or compiler. The context (including stack and memory) +must be swapped in and out of the calling functions context. A desired feature is having *pure* functions, which do not modify the state of memory, and realising +them through `JUMP` requires a bigger effort from the compiler as opposed to being able to use `CALL`s. + +Using call-to-self provides the guarantee that when making an internal call the function can rely on a clear reset state of memory or context, benefiting both +contract writers and contract consumers against potentially undetetected edge cases were memory could poison the context of the internal function. + +Because of the `JUMP` usage for internal functions a smart contract languages are also at risk of reaching the stack depth limit considerbly faster, if nested +function calls with many in and/or outputs are required. + +Reducing the gas cost, and thereby incentivising of using call-to-self instead of `JUMP`s for the internal function implementation will also benefit static +analyzers and tracers. + +## Specification +If `block.number >= FORK_BLKNUM`, then decrease the cost of `CALL`, `DELEGATECALL`, `CALLCODE` and `STATICCALL` from 700 to 40, +if and only if, the destination address of the call equals to the address of the caller. + +## Rationale +EIP150 has increased the cost of these instructions from 40 to 700 to more fairly charge for loading new contracts from disk, e.g. to reflect the I/O charge more closely. +By assuming that 660 is the cost of loading a contract from disk, one can assume that the original 40 gas is a fair cost of creating a new VM instance of an already loaded contract code. + +## Backwards Compatibility +This should pose no risk to backwards compatibility. Currently existing contracts should not notice the difference, just see cheaper execution. +With EIP150 contract (and language) developers had a lesson that relying on strict gas costs is not feasible as costs may change. +The impact of this EIP is even less that of EIP150 because the costs are changing downwards and not upwards. + +## Test Cases +TBA + +## Implementation +TBA + +## Copyright +Copyright and related rights waived via [CC0](../LICENSE.md). diff --git a/EIPS/eip-1386.md b/EIPS/eip-1386.md new file mode 100644 index 0000000..a832170 --- /dev/null +++ b/EIPS/eip-1386.md @@ -0,0 +1,88 @@ +--- +eip: 1386 +title: Attestation management contract +author: Weiwu Zhang , James Sangalli
./contracts/ERC1820Registry.sol
+{
+ "compiler": {
+ "version": "0.5.3+commit.10d17f24"
+ },
+ "language": "Solidity",
+ "output": {
+ "abi": [
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "_addr",
+ "type": "address"
+ },
+ {
+ "name": "_interfaceHash",
+ "type": "bytes32"
+ },
+ {
+ "name": "_implementer",
+ "type": "address"
+ }
+ ],
+ "name": "setInterfaceImplementer",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "_addr",
+ "type": "address"
+ }
+ ],
+ "name": "getManager",
+ "outputs": [
+ {
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "_addr",
+ "type": "address"
+ },
+ {
+ "name": "_newManager",
+ "type": "address"
+ }
+ ],
+ "name": "setManager",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "_interfaceName",
+ "type": "string"
+ }
+ ],
+ "name": "interfaceHash",
+ "outputs": [
+ {
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "pure",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "_contract",
+ "type": "address"
+ },
+ {
+ "name": "_interfaceId",
+ "type": "bytes4"
+ }
+ ],
+ "name": "updateERC165Cache",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "_addr",
+ "type": "address"
+ },
+ {
+ "name": "_interfaceHash",
+ "type": "bytes32"
+ }
+ ],
+ "name": "getInterfaceImplementer",
+ "outputs": [
+ {
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "_contract",
+ "type": "address"
+ },
+ {
+ "name": "_interfaceId",
+ "type": "bytes4"
+ }
+ ],
+ "name": "implementsERC165InterfaceNoCache",
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "_contract",
+ "type": "address"
+ },
+ {
+ "name": "_interfaceId",
+ "type": "bytes4"
+ }
+ ],
+ "name": "implementsERC165Interface",
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "addr",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "name": "interfaceHash",
+ "type": "bytes32"
+ },
+ {
+ "indexed": true,
+ "name": "implementer",
+ "type": "address"
+ }
+ ],
+ "name": "InterfaceImplementerSet",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "addr",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "name": "newManager",
+ "type": "address"
+ }
+ ],
+ "name": "ManagerChanged",
+ "type": "event"
+ }
+ ],
+ "devdoc": {
+ "author": "Jordi Baylina and Jacques Dafflon",
+ "methods": {
+ "getInterfaceImplementer(address,bytes32)": {
+ "params": {
+ "_addr": "Address being queried for the implementer of an interface. (If '_addr' is the zero address then 'msg.sender' is assumed.)",
+ "_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 '_addr' or '0' if '_addr' did not register an implementer for this interface."
+ },
+ "getManager(address)": {
+ "params": {
+ "_addr": "Address for which to return the manager."
+ },
+ "return": "Address of the manager for a given address."
+ },
+ "implementsERC165Interface(address,bytes4)": {
+ "params": {
+ "_contract": "Address of the contract to check.",
+ "_interfaceId": "ERC165 interface to check."
+ },
+ "return": "True if '_contract' implements '_interfaceId', false otherwise."
+ },
+ "implementsERC165InterfaceNoCache(address,bytes4)": {
+ "params": {
+ "_contract": "Address of the contract to check.",
+ "_interfaceId": "ERC165 interface to check."
+ },
+ "return": "True if '_contract' implements '_interfaceId', false otherwise."
+ },
+ "interfaceHash(string)": {
+ "params": {
+ "_interfaceName": "Name of the interface."
+ },
+ "return": "The keccak256 hash of an interface name."
+ },
+ "setInterfaceImplementer(address,bytes32,address)": {
+ "params": {
+ "_addr": "Address for which to set the interface. (If '_addr' is the zero address then 'msg.sender' is assumed.)",
+ "_implementer": "Contract address implementing '_interfaceHash' for '_addr'.",
+ "_interfaceHash": "Keccak256 hash of the name of the interface as a string. E.g., 'web3.utils.keccak256(\"ERC777TokensRecipient\")' for the 'ERC777TokensRecipient' interface."
+ }
+ },
+ "setManager(address,address)": {
+ "params": {
+ "_addr": "Address for which to set the new manager.",
+ "_newManager": "Address of the new manager for 'addr'. (Pass '0x0' to reset the manager to '_addr'.)"
+ }
+ },
+ "updateERC165Cache(address,bytes4)": {
+ "params": {
+ "_contract": "Address of the contract for which to update the cache.",
+ "_interfaceId": "ERC165 interface for which to update the cache."
+ }
+ }
+ },
+ "title": "ERC1820 Pseudo-introspection Registry Contract"
+ },
+ "userdoc": {
+ "methods": {
+ "getInterfaceImplementer(address,bytes32)": {
+ "notice": "Query if an address implements an interface and through which contract."
+ },
+ "getManager(address)": {
+ "notice": "Get the manager of an address."
+ },
+ "implementsERC165InterfaceNoCache(address,bytes4)": {
+ "notice": "Checks whether a contract implements an ERC165 interface or not without using nor updating the cache."
+ },
+ "interfaceHash(string)": {
+ "notice": "Compute the keccak256 hash of an interface given its name."
+ },
+ "setInterfaceImplementer(address,bytes32,address)": {
+ "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.)"
+ },
+ "setManager(address,address)": {
+ "notice": "Sets '_newManager' as manager for '_addr'. The new manager will be able to call 'setInterfaceImplementer' for '_addr'."
+ },
+ "updateERC165Cache(address,bytes4)": {
+ "notice": "Updates the cache with whether the contract implements an ERC165 interface or not."
+ }
+ },
+ "notice": "This contract is the official implementation of the ERC1820 Registry.For more details, see https://eips.ethereum.org/EIPS/eip-1820"
+ }
+ },
+ "settings": {
+ "compilationTarget": {
+ "./contracts/ERC1820Registry.sol": "ERC1820Registry"
+ },
+ "evmVersion": "byzantium",
+ "libraries": {},
+ "optimizer": {
+ "enabled": true,
+ "runs": 200
+ },
+ "remappings": []
+ },
+ "sources": {
+ "./contracts/ERC1820Registry.sol": {
+ "content": "/* ERC1820 Pseudo-introspection Registry Contract\n * This standard defines a universal registry smart contract where any address (contract or regular account) can\n * register which interface it supports and which smart contract is responsible for its implementation.\n *\n * Written in 2019 by Jordi Baylina and Jacques Dafflon\n *\n * To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to\n * this software to the public domain worldwide. This software is distributed without any warranty.\n *\n * You should have received a copy of the CC0 Public Domain Dedication along with this software. If not, see\n * .\n *\n * ███████╗██████╗ ██████╗ ██╗ █████╗ ██████╗ ██████╗\n * ██╔════╝██╔══██╗██╔════╝███║██╔══██╗╚════██╗██╔═████╗\n * █████╗ ██████╔╝██║ ╚██║╚█████╔╝ █████╔╝██║██╔██║\n * ██╔══╝ ██╔══██╗██║ ██║██╔══██╗██╔═══╝ ████╔╝██║\n * ███████╗██║ ██║╚██████╗ ██║╚█████╔╝███████╗╚██████╔╝\n * ╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚════╝ ╚══════╝ ╚═════╝\n *\n * ██████╗ ███████╗ ██████╗ ██╗███████╗████████╗██████╗ ██╗ ██╗\n * ██╔══██╗██╔════╝██╔════╝ ██║██╔════╝╚══██╔══╝██╔══██╗╚██╗ ██╔╝\n * ██████╔╝█████╗ ██║ ███╗██║███████╗ ██║ ██████╔╝ ╚████╔╝\n * ██╔══██╗██╔══╝ ██║ ██║██║╚════██║ ██║ ██╔══██╗ ╚██╔╝\n * ██║ ██║███████╗╚██████╔╝██║███████║ ██║ ██║ ██║ ██║\n * ╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═╝╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝\n *\n */\npragma solidity 0.5.3;\n// IV is value needed to have a vanity address starting with '0x1820'.\n// IV: 53759\n\n/// @dev The interface a contract MUST implement if it is the implementer of\n/// some (other) interface for any address other than itself.\ninterface ERC1820ImplementerInterface {\n /// @notice Indicates whether the contract implements the interface 'interfaceHash' for the address 'addr' or not.\n /// @param interfaceHash keccak256 hash of the name of the interface\n /// @param addr Address for which the contract will implement the interface\n /// @return ERC1820_ACCEPT_MAGIC only if the contract implements 'interfaceHash' for the address 'addr'.\n function canImplementInterfaceForAddress(bytes32 interfaceHash, address addr) external view returns(bytes32);\n}\n\n\n/// @title ERC1820 Pseudo-introspection Registry Contract\n/// @author Jordi Baylina and Jacques Dafflon\n/// @notice This contract is the official implementation of the ERC1820 Registry.\n/// @notice For more details, see https://eips.ethereum.org/EIPS/eip-1820\ncontract ERC1820Registry {\n /// @notice ERC165 Invalid ID.\n bytes4 constant internal INVALID_ID = 0xffffffff;\n /// @notice Method ID for the ERC165 supportsInterface method (= `bytes4(keccak256('supportsInterface(bytes4)'))`).\n bytes4 constant internal ERC165ID = 0x01ffc9a7;\n /// @notice Magic value which is returned if a contract implements an interface on behalf of some other address.\n bytes32 constant internal ERC1820_ACCEPT_MAGIC = keccak256(abi.encodePacked(\"ERC1820_ACCEPT_MAGIC\"));\n\n /// @notice mapping from addresses and interface hashes to their implementers.\n mapping(address => mapping(bytes32 => address)) internal interfaces;\n /// @notice mapping from addresses to their manager.\n mapping(address => address) internal managers;\n /// @notice flag for each address and erc165 interface to indicate if it is cached.\n mapping(address => mapping(bytes4 => bool)) internal erc165Cached;\n\n /// @notice Indicates a contract is the 'implementer' of 'interfaceHash' for 'addr'.\n event InterfaceImplementerSet(address indexed addr, bytes32 indexed interfaceHash, address indexed implementer);\n /// @notice Indicates 'newManager' is the address of the new manager for 'addr'.\n event ManagerChanged(address indexed addr, address indexed newManager);\n\n /// @notice Query if an address implements an interface and through which contract.\n /// @param _addr Address being queried for the implementer of an interface.\n /// (If '_addr' is the zero address then 'msg.sender' is assumed.)\n /// @param _interfaceHash Keccak256 hash of the name of the interface as a string.\n /// E.g., 'web3.utils.keccak256(\"ERC777TokensRecipient\")' for the 'ERC777TokensRecipient' interface.\n /// @return The address of the contract which implements the interface '_interfaceHash' for '_addr'\n /// or '0' if '_addr' did not register an implementer for this interface.\n function getInterfaceImplementer(address _addr, bytes32 _interfaceHash) external view returns (address) {\n address addr = _addr == address(0) ? msg.sender : _addr;\n if (isERC165Interface(_interfaceHash)) {\n bytes4 erc165InterfaceHash = bytes4(_interfaceHash);\n return implementsERC165Interface(addr, erc165InterfaceHash) ? addr : address(0);\n }\n return interfaces[addr][_interfaceHash];\n }\n\n /// @notice Sets the contract which implements a specific interface for an address.\n /// Only the manager defined for that address can set it.\n /// (Each address is the manager for itself until it sets a new manager.)\n /// @param _addr Address for which to set the interface.\n /// (If '_addr' is the zero address then 'msg.sender' is assumed.)\n /// @param _interfaceHash Keccak256 hash of the name of the interface as a string.\n /// E.g., 'web3.utils.keccak256(\"ERC777TokensRecipient\")' for the 'ERC777TokensRecipient' interface.\n /// @param _implementer Contract address implementing '_interfaceHash' for '_addr'.\n function setInterfaceImplementer(address _addr, bytes32 _interfaceHash, address _implementer) external {\n address addr = _addr == address(0) ? msg.sender : _addr;\n require(getManager(addr) == msg.sender, \"Not the manager\");\n\n require(!isERC165Interface(_interfaceHash), \"Must not be an ERC165 hash\");\n if (_implementer != address(0) && _implementer != msg.sender) {\n require(\n ERC1820ImplementerInterface(_implementer)\n .canImplementInterfaceForAddress(_interfaceHash, addr) == ERC1820_ACCEPT_MAGIC,\n \"Does not implement the interface\"\n );\n }\n interfaces[addr][_interfaceHash] = _implementer;\n emit InterfaceImplementerSet(addr, _interfaceHash, _implementer);\n }\n\n /// @notice Sets '_newManager' as manager for '_addr'.\n /// The new manager will be able to call 'setInterfaceImplementer' for '_addr'.\n /// @param _addr Address for which to set the new manager.\n /// @param _newManager Address of the new manager for 'addr'. (Pass '0x0' to reset the manager to '_addr'.)\n function setManager(address _addr, address _newManager) external {\n require(getManager(_addr) == msg.sender, \"Not the manager\");\n managers[_addr] = _newManager == _addr ? address(0) : _newManager;\n emit ManagerChanged(_addr, _newManager);\n }\n\n /// @notice Get the manager of an address.\n /// @param _addr Address for which to return the manager.\n /// @return Address of the manager for a given address.\n function getManager(address _addr) public view returns(address) {\n // By default the manager of an address is the same address\n if (managers[_addr] == address(0)) {\n return _addr;\n } else {\n return managers[_addr];\n }\n }\n\n /// @notice Compute the keccak256 hash of an interface given its name.\n /// @param _interfaceName Name of the interface.\n /// @return The keccak256 hash of an interface name.\n function interfaceHash(string calldata _interfaceName) external pure returns(bytes32) {\n return keccak256(abi.encodePacked(_interfaceName));\n }\n\n /* --- ERC165 Related Functions --- */\n /* --- Developed in collaboration with William Entriken. --- */\n\n /// @notice Updates the cache with whether the contract implements an ERC165 interface or not.\n /// @param _contract Address of the contract for which to update the cache.\n /// @param _interfaceId ERC165 interface for which to update the cache.\n function updateERC165Cache(address _contract, bytes4 _interfaceId) external {\n interfaces[_contract][_interfaceId] = implementsERC165InterfaceNoCache(\n _contract, _interfaceId) ? _contract : address(0);\n erc165Cached[_contract][_interfaceId] = true;\n }\n\n /// @notice Checks whether a contract implements an ERC165 interface or not.\n // If the result is not cached a direct lookup on the contract address is performed.\n // If the result is not cached or the cached value is out-of-date, the cache MUST be updated manually by calling\n // 'updateERC165Cache' with the contract address.\n /// @param _contract Address of the contract to check.\n /// @param _interfaceId ERC165 interface to check.\n /// @return True if '_contract' implements '_interfaceId', false otherwise.\n function implementsERC165Interface(address _contract, bytes4 _interfaceId) public view returns (bool) {\n if (!erc165Cached[_contract][_interfaceId]) {\n return implementsERC165InterfaceNoCache(_contract, _interfaceId);\n }\n return interfaces[_contract][_interfaceId] == _contract;\n }\n\n /// @notice Checks whether a contract implements an ERC165 interface or not without using nor updating the cache.\n /// @param _contract Address of the contract to check.\n /// @param _interfaceId ERC165 interface to check.\n /// @return True if '_contract' implements '_interfaceId', false otherwise.\n function implementsERC165InterfaceNoCache(address _contract, bytes4 _interfaceId) public view returns (bool) {\n uint256 success;\n uint256 result;\n\n (success, result) = noThrowCall(_contract, ERC165ID);\n if (success == 0 || result == 0) {\n return false;\n }\n\n (success, result) = noThrowCall(_contract, INVALID_ID);\n if (success == 0 || result != 0) {\n return false;\n }\n\n (success, result) = noThrowCall(_contract, _interfaceId);\n if (success == 1 && result == 1) {\n return true;\n }\n return false;\n }\n\n /// @notice Checks whether the hash is a ERC165 interface (ending with 28 zeroes) or not.\n /// @param _interfaceHash The hash to check.\n /// @return True if '_interfaceHash' is an ERC165 interface (ending with 28 zeroes), false otherwise.\n function isERC165Interface(bytes32 _interfaceHash) internal pure returns (bool) {\n return _interfaceHash & 0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0;\n }\n\n /// @dev Make a call on a contract without throwing if the function does not exist.\n function noThrowCall(address _contract, bytes4 _interfaceId)\n internal view returns (uint256 success, uint256 result)\n {\n bytes4 erc165ID = ERC165ID;\n\n assembly {\n let x := mload(0x40) // Find empty storage location using \"free memory pointer\"\n mstore(x, erc165ID) // Place signature at beginning of empty storage\n mstore(add(x, 0x04), _interfaceId) // Place first argument directly next to signature\n\n success := staticcall(\n 30000, // 30k gas\n _contract, // To addr\n x, // Inputs are stored at location x\n 0x24, // Inputs are 36 (4 + 32) bytes long\n x, // Store output over input (saves space)\n 0x20 // Outputs are 32 bytes long\n )\n\n result := mload(x) // Load the result\n }\n }\n}\n",
+ "keccak256": "0x64025ecebddb6e126a5075c1fd6c01de2840492668e2909cef7157040a9d1945"
+ }
+ },
+ "version": 1
+ }
+
+