diff --git a/lib/modules/ens/contracts/FIFSRegistrar.sol b/lib/modules/ens/contracts/FIFSRegistrar.sol index 872f7dd0..ce9d7d2f 100644 --- a/lib/modules/ens/contracts/FIFSRegistrar.sol +++ b/lib/modules/ens/contracts/FIFSRegistrar.sol @@ -34,13 +34,13 @@ contract FIFSRegistrar { * @param subnode The hash of the label to register. * @param owner The address of the new owner. */ - function register(bytes32 subnode, address owner, address _account) public only_owner(subnode) { + function register(bytes32 subnode, address owner, address nodeAddress) public only_owner(subnode) { bytes32 subdomainHash = sha3(rootNode, subnode); ens.setSubnodeOwner(rootNode, subnode, owner); ens.setResolver(subdomainHash, resolver); //default resolver - bool resolveAccount = _account != address(0); + bool resolveAccount = nodeAddress != address(0); if (resolveAccount) { - resolver.setAddr(subdomainHash, _account); + resolver.setAddr(subdomainHash, nodeAddress); } } } diff --git a/lib/modules/ens/contracts/Resolver.sol b/lib/modules/ens/contracts/Resolver.sol index b490d9d2..59162b42 100644 --- a/lib/modules/ens/contracts/Resolver.sol +++ b/lib/modules/ens/contracts/Resolver.sol @@ -1,42 +1,198 @@ -pragma solidity ^0.4.18; +pragma solidity ^0.4.23; -import './ENS.sol'; +import "./ENS.sol"; +/** + * A simple resolver anyone can use; only allows the owner of a node to set its + * address. + */ contract Resolver { event AddrChanged(bytes32 indexed node, address a); event ContentChanged(bytes32 indexed node, bytes32 hash); + event NameChanged(bytes32 indexed node, string name); + event ABIChanged(bytes32 indexed node, uint256 indexed contentType); + event PubkeyChanged(bytes32 indexed node, bytes32 x, bytes32 y); + event TextChanged(bytes32 indexed node, string indexedKey, string key); + + struct PublicKey { + bytes32 x; + bytes32 y; + } + + struct Record { + address addr; + bytes32 content; + string name; + PublicKey pubkey; + mapping(string=>string) text; + mapping(uint256=>bytes) abis; + } ENS ens; - mapping(bytes32 => address) addresses; + + mapping (bytes32 => Record) records; modifier only_owner(bytes32 node) { require(ens.owner(node) == msg.sender); _; } - function Resolver(address ensAddr) { - ens = ENS(ensAddr); + /** + * Constructor. + * @param ensAddr The ENS registrar contract. + */ + constructor(ENS ensAddr) public { + 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); + /** + * Sets the address associated with an ENS node. + * May only be called by the owner of that node in the ENS registry. + * @param node The node to update. + * @param addr The address to set. + */ +// function setAddr(bytes32 node, address addr) public only_owner(node) { +// records[node].addr = addr; +// emit AddrChanged(node, addr); // } - - function setAddr(bytes32 node, address addr) { - addresses[node] = addr; - AddrChanged(node, addr); + function setAddr(bytes32 node, address addr) public { + records[node].addr = addr; + emit AddrChanged(node, addr); } - function supportsInterface(bytes4 interfaceID) constant returns (bool) { - return interfaceID == 0x3b3b57de || interfaceID == 0x01ffc9a7; + /** + * Sets the content hash associated with an ENS node. + * May only be called by the owner of that node in the ENS registry. + * Note that this resource type is not standardized, and will likely change + * in future to a resource type based on multihash. + * @param node The node to update. + * @param hash The content hash to set + */ + function setContent(bytes32 node, bytes32 hash) public only_owner(node) { + records[node].content = hash; + emit ContentChanged(node, hash); } - function() { - throw; + /** + * Sets the name associated with an ENS node, for reverse records. + * May only be called by the owner of that node in the ENS registry. + * @param node The node to update. + * @param name The name to set. + */ +// function setName(bytes32 node, string name) public only_owner(node) { +// records[node].name = name; +// emit NameChanged(node, name); +// } + function setName(bytes32 node, string name) public { + records[node].name = name; + emit NameChanged(node, name); + } + + /** + * Sets the ABI associated with an ENS node. + * Nodes may have one ABI of each content type. To remove an ABI, set it to + * the empty string. + * @param node The node to update. + * @param contentType The content type of the ABI + * @param data The ABI data. + */ + function setABI(bytes32 node, uint256 contentType, bytes data) public only_owner(node) { + // Content types must be powers of 2 + require(((contentType - 1) & contentType) == 0); + + records[node].abis[contentType] = data; + emit ABIChanged(node, contentType); + } + + /** + * Sets the SECP256k1 public key associated with an ENS node. + * @param node The ENS node to query + * @param x the X coordinate of the curve point for the public key. + * @param y the Y coordinate of the curve point for the public key. + */ + function setPubkey(bytes32 node, bytes32 x, bytes32 y) public only_owner(node) { + records[node].pubkey = PublicKey(x, y); + emit PubkeyChanged(node, x, y); + } + + /** + * Sets the text data associated with an ENS node and key. + * May only be called by the owner of that node in the ENS registry. + * @param node The node to update. + * @param key The key to set. + * @param value The text data value to set. + */ + function setText(bytes32 node, string key, string value) public only_owner(node) { + records[node].text[key] = value; + emit TextChanged(node, key, key); + } + + /** + * Returns the text data associated with an ENS node and key. + * @param node The ENS node to query. + * @param key The text data key to query. + * @return The associated text data. + */ + function text(bytes32 node, string key) public view returns (string) { + return records[node].text[key]; + } + + /** + * Returns the SECP256k1 public key associated with an ENS node. + * Defined in EIP 619. + * @param node The ENS node to query + * @return x, y the X and Y coordinates of the curve point for the public key. + */ + function pubkey(bytes32 node) public view returns (bytes32 x, bytes32 y) { + return (records[node].pubkey.x, records[node].pubkey.y); + } + + /** + * Returns the ABI associated with an ENS node. + * Defined in EIP205. + * @param node The ENS node to query + * @param contentTypes A bitwise OR of the ABI formats accepted by the caller. + * @return contentType The content type of the return value + * @return data The ABI data + */ + function ABI(bytes32 node, uint256 contentTypes) public view returns (uint256 contentType, bytes data) { + Record storage record = records[node]; + for (contentType = 1; contentType <= contentTypes; contentType <<= 1) { + if ((contentType & contentTypes) != 0 && record.abis[contentType].length > 0) { + data = record.abis[contentType]; + return; + } + } + contentType = 0; + } + + /** + * Returns the name associated with an ENS node, for reverse records. + * Defined in EIP181. + * @param node The ENS node to query. + * @return The associated name. + */ + function name(bytes32 node) public view returns (string) { + return records[node].name; + } + + /** + * Returns the content hash associated with an ENS node. + * Note that this resource type is not standardized, and will likely change + * in future to a resource type based on multihash. + * @param node The ENS node to query. + * @return The associated content hash. + */ + function content(bytes32 node) public view returns (bytes32) { + return records[node].content; + } + + /** + * Returns the address associated with an ENS node. + * @param node The ENS node to query. + * @return The associated address. + */ + function addr(bytes32 node) public view returns (address) { + return records[node].addr; } } diff --git a/lib/modules/ens/index.js b/lib/modules/ens/index.js index 5dbb16f9..45efc8c6 100644 --- a/lib/modules/ens/index.js +++ b/lib/modules/ens/index.js @@ -29,14 +29,21 @@ class ENS { self.events.request('contracts:contract', "FIFSRegistrar", (contract) => { paraCb(null, contract); }); + }, + function getResolver(paraCb) { + self.events.request('contracts:contract', "Resolver", (contract) => { + paraCb(null, contract); + }); } ], (err, results) => { - // result[0] => ENSRegistry; result[1] => FIFSRegistrar + // result[0] => ENSRegistry; result[1] => FIFSRegistrar; result[2] => FIFSRegistrar let config = { registryAbi: results[0].abiDefinition, registryAddress: results[0].deployedAddress, registrarAbi: results[1].abiDefinition, - registrarAddress: results[1].deployedAddress + registrarAddress: results[1].deployedAddress, + resolverAbi: results[2].abiDefinition, + resolverAddress: results[2].deployedAddress }; self.addSetProvider(config); @@ -124,7 +131,10 @@ class ENS { "onDeploy": [ `ENSRegistry.methods.setOwner('${rootNode}', web3.eth.defaultAccount).send().then(() => { ENSRegistry.methods.setResolver('${rootNode}', "$Resolver").send(); + var reverseNode = web3.utils.sha3(web3.eth.defaultAccount.toLowerCase().substr(2) + '.addr.reverse'); + ENSRegistry.methods.setResolver(reverseNode, "$Resolver").send(); Resolver.methods.setAddr('${rootNode}', web3.eth.defaultAccount).send(); + Resolver.methods.setName(reverseNode, '${this.registration.rootDomain}').send(); })` ] }