From 42fe72392ba00b569c384b48b61c796fc3634941 Mon Sep 17 00:00:00 2001 From: VoR0220 Date: Wed, 13 Jun 2018 12:29:43 -0500 Subject: [PATCH 01/17] add ens contracts Signed-off-by: VoR0220 --- lib/modules/ens/contracts/DNSResolver.sol | 27 + lib/modules/ens/contracts/Deed.sol | 85 +++ .../ens/contracts/DefaultReverseResolver.sol | 47 ++ lib/modules/ens/contracts/ENS.sol | 26 + lib/modules/ens/contracts/ENSRegistry.sol | 99 ++++ lib/modules/ens/contracts/FIFSRegistrar.sol | 36 ++ .../ens/contracts/HashRegistrarSimplified.sol | 535 ++++++++++++++++++ lib/modules/ens/contracts/PublicResolver.sol | 238 ++++++++ .../ens/contracts/ResolverInterface.sol | 10 + .../ens/contracts/ReverseRegistrar.sol | 117 ++++ lib/modules/ens/contracts/TestRegistrar.sol | 37 ++ 11 files changed, 1257 insertions(+) create mode 100644 lib/modules/ens/contracts/DNSResolver.sol create mode 100644 lib/modules/ens/contracts/Deed.sol create mode 100644 lib/modules/ens/contracts/DefaultReverseResolver.sol create mode 100644 lib/modules/ens/contracts/ENS.sol create mode 100644 lib/modules/ens/contracts/ENSRegistry.sol create mode 100644 lib/modules/ens/contracts/FIFSRegistrar.sol create mode 100644 lib/modules/ens/contracts/HashRegistrarSimplified.sol create mode 100644 lib/modules/ens/contracts/PublicResolver.sol create mode 100644 lib/modules/ens/contracts/ResolverInterface.sol create mode 100644 lib/modules/ens/contracts/ReverseRegistrar.sol create mode 100644 lib/modules/ens/contracts/TestRegistrar.sol diff --git a/lib/modules/ens/contracts/DNSResolver.sol b/lib/modules/ens/contracts/DNSResolver.sol new file mode 100644 index 000000000..027f45423 --- /dev/null +++ b/lib/modules/ens/contracts/DNSResolver.sol @@ -0,0 +1,27 @@ +pragma solidity ^0.4.18; + +contract DNSResolver { + address public owner; + mapping (bytes32 => bytes) zones; + + modifier owner_only { + require(msg.sender == owner); + _; + } + + function DNSResolver() public { + owner = msg.sender; + } + + function setDnsrr(bytes32 node, bytes data) public owner_only { + zones[node] = data; + } + + function dnsrr(bytes32 node) public view returns (bytes) { + return zones[node]; + } + + function supportsInterface(bytes4 interfaceID) public pure returns (bool) { + return interfaceID == 0x126a710e; + } +} diff --git a/lib/modules/ens/contracts/Deed.sol b/lib/modules/ens/contracts/Deed.sol new file mode 100644 index 000000000..4c859d6e7 --- /dev/null +++ b/lib/modules/ens/contracts/Deed.sol @@ -0,0 +1,85 @@ +pragma solidity ^0.4.18; + +/** + * @title Deed to hold ether in exchange for ownership of a node + * @dev The deed can be controlled only by the registrar and can only send ether back to the owner. + */ +contract Deed { + + address constant burn = 0xdead; + + address public registrar; + address public owner; + address public previousOwner; + + uint public creationDate; + uint public value; + + bool active; + + event OwnerChanged(address newOwner); + event DeedClosed(); + + modifier onlyRegistrar { + require(msg.sender == registrar); + _; + } + + modifier onlyActive { + require(active); + _; + } + + function Deed(address _owner) public payable { + owner = _owner; + registrar = msg.sender; + creationDate = now; + active = true; + value = msg.value; + } + + function setOwner(address newOwner) public onlyRegistrar { + require(newOwner != 0); + previousOwner = owner; // This allows contracts to check who sent them the ownership + owner = newOwner; + OwnerChanged(newOwner); + } + + function setRegistrar(address newRegistrar) public onlyRegistrar { + registrar = newRegistrar; + } + + function setBalance(uint newValue, bool throwOnFailure) public onlyRegistrar onlyActive { + // Check if it has enough balance to set the value + require(value >= newValue); + value = newValue; + // Send the difference to the owner + require(owner.send(this.balance - newValue) || !throwOnFailure); + } + + /** + * @dev Close a deed and refund a specified fraction of the bid value + * + * @param refundRatio The amount*1/1000 to refund + */ + function closeDeed(uint refundRatio) public onlyRegistrar onlyActive { + active = false; + require(burn.send(((1000 - refundRatio) * this.balance)/1000)); + DeedClosed(); + destroyDeed(); + } + + /** + * @dev Close a deed and refund a specified fraction of the bid value + */ + function destroyDeed() public { + require(!active); + + // Instead of selfdestruct(owner), invoke owner fallback function to allow + // owner to log an event if desired; but owner should also be aware that + // its fallback function can also be invoked by setBalance + if (owner.send(this.balance)) { + selfdestruct(burn); + } + } +} diff --git a/lib/modules/ens/contracts/DefaultReverseResolver.sol b/lib/modules/ens/contracts/DefaultReverseResolver.sol new file mode 100644 index 000000000..c9df305be --- /dev/null +++ b/lib/modules/ens/contracts/DefaultReverseResolver.sol @@ -0,0 +1,47 @@ +pragma solidity ^0.4.18; + +import "./ReverseRegistrar.sol"; + +/** + * @dev Provides a default implementation of a resolver for reverse records, + * which permits only the owner to update it. + */ +contract DefaultReverseResolver is Resolver { + // namehash('addr.reverse') + bytes32 constant ADDR_REVERSE_NODE = 0x91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e2; + + ENS public ens; + mapping (bytes32 => string) public name; + + /** + * @dev Only permits calls by the reverse registrar. + * @param node The node permission is required for. + */ + modifier owner_only(bytes32 node) { + require(msg.sender == ens.owner(node)); + _; + } + + /** + * @dev Constructor + * @param ensAddr The address of the ENS registry. + */ + function DefaultReverseResolver(ENS ensAddr) public { + ens = ensAddr; + + // Assign ownership of the reverse record to our deployer + ReverseRegistrar registrar = ReverseRegistrar(ens.owner(ADDR_REVERSE_NODE)); + if (address(registrar) != 0) { + registrar.claim(msg.sender); + } + } + + /** + * @dev Sets the name for a node. + * @param node The node to update. + * @param _name The name to set. + */ + function setName(bytes32 node, string _name) public owner_only(node) { + name[node] = _name; + } +} diff --git a/lib/modules/ens/contracts/ENS.sol b/lib/modules/ens/contracts/ENS.sol new file mode 100644 index 000000000..61e0edac3 --- /dev/null +++ b/lib/modules/ens/contracts/ENS.sol @@ -0,0 +1,26 @@ +pragma solidity ^0.4.18; + +interface ENS { + + // Logged when the owner of a node assigns a new owner to a subnode. + event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner); + + // Logged when the owner of a node transfers ownership to a new account. + event Transfer(bytes32 indexed node, address owner); + + // Logged when the resolver for a node changes. + event NewResolver(bytes32 indexed node, address resolver); + + // Logged when the TTL of a node changes + event NewTTL(bytes32 indexed node, uint64 ttl); + + + function setSubnodeOwner(bytes32 node, bytes32 label, address owner) public; + function setResolver(bytes32 node, address resolver) public; + function setOwner(bytes32 node, address owner) public; + function setTTL(bytes32 node, uint64 ttl) public; + function owner(bytes32 node) public view returns (address); + function resolver(bytes32 node) public view returns (address); + function ttl(bytes32 node) public view returns (uint64); + +} diff --git a/lib/modules/ens/contracts/ENSRegistry.sol b/lib/modules/ens/contracts/ENSRegistry.sol new file mode 100644 index 000000000..251c11006 --- /dev/null +++ b/lib/modules/ens/contracts/ENSRegistry.sol @@ -0,0 +1,99 @@ +pragma solidity ^0.4.18; + +import './ENS.sol'; + +/** + * The ENS registry contract. + */ +contract ENSRegistry is ENS { + struct Record { + address owner; + address resolver; + uint64 ttl; + } + + mapping (bytes32 => Record) records; + + // Permits modifications only by the owner of the specified node. + modifier only_owner(bytes32 node) { + require(records[node].owner == msg.sender); + _; + } + + /** + * @dev Constructs a new ENS registrar. + */ + function ENSRegistry() public { + records[0x0].owner = msg.sender; + } + + /** + * @dev Transfers ownership of a node to a new address. May only be called by the current owner of the node. + * @param node The node to transfer ownership of. + * @param owner The address of the new owner. + */ + function setOwner(bytes32 node, address owner) public only_owner(node) { + Transfer(node, owner); + records[node].owner = owner; + } + + /** + * @dev Transfers ownership of a subnode keccak256(node, label) to a new address. May only be called by the owner of the parent node. + * @param node The parent node. + * @param label The hash of the label specifying the subnode. + * @param owner The address of the new owner. + */ + function setSubnodeOwner(bytes32 node, bytes32 label, address owner) public only_owner(node) { + var subnode = keccak256(node, label); + NewOwner(node, label, owner); + records[subnode].owner = owner; + } + + /** + * @dev Sets the resolver address for the specified node. + * @param node The node to update. + * @param resolver The address of the resolver. + */ + function setResolver(bytes32 node, address resolver) public only_owner(node) { + NewResolver(node, resolver); + records[node].resolver = resolver; + } + + /** + * @dev Sets the TTL for the specified node. + * @param node The node to update. + * @param ttl The TTL in seconds. + */ + function setTTL(bytes32 node, uint64 ttl) public only_owner(node) { + NewTTL(node, ttl); + records[node].ttl = ttl; + } + + /** + * @dev Returns the address that owns the specified node. + * @param node The specified node. + * @return address of the owner. + */ + function owner(bytes32 node) public view returns (address) { + return records[node].owner; + } + + /** + * @dev Returns the address of the resolver for the specified node. + * @param node The specified node. + * @return address of the resolver. + */ + function resolver(bytes32 node) public view returns (address) { + return records[node].resolver; + } + + /** + * @dev Returns the TTL of a node, and any records associated with it. + * @param node The specified node. + * @return ttl of the node. + */ + function ttl(bytes32 node) public view returns (uint64) { + return records[node].ttl; + } + +} diff --git a/lib/modules/ens/contracts/FIFSRegistrar.sol b/lib/modules/ens/contracts/FIFSRegistrar.sol new file mode 100644 index 000000000..62b7f270b --- /dev/null +++ b/lib/modules/ens/contracts/FIFSRegistrar.sol @@ -0,0 +1,36 @@ +pragma solidity ^0.4.18; + +import './ENS.sol'; + +/** + * A registrar that allocates subdomains to the first person to claim them. + */ +contract FIFSRegistrar { + ENS ens; + bytes32 rootNode; + + modifier only_owner(bytes32 subnode) { + address currentOwner = ens.owner(keccak256(rootNode, subnode)); + require(currentOwner == 0 || currentOwner == msg.sender); + _; + } + + /** + * Constructor. + * @param ensAddr The address of the ENS registry. + * @param node The node that this registrar administers. + */ + function FIFSRegistrar(ENS ensAddr, bytes32 node) public { + ens = ensAddr; + rootNode = node; + } + + /** + * Register a name, or change the owner of an existing registration. + * @param subnode The hash of the label to register. + * @param owner The address of the new owner. + */ + function register(bytes32 subnode, address owner) public only_owner(subnode) { + ens.setSubnodeOwner(rootNode, subnode, owner); + } +} diff --git a/lib/modules/ens/contracts/HashRegistrarSimplified.sol b/lib/modules/ens/contracts/HashRegistrarSimplified.sol new file mode 100644 index 000000000..35952ae8f --- /dev/null +++ b/lib/modules/ens/contracts/HashRegistrarSimplified.sol @@ -0,0 +1,535 @@ +pragma solidity ^0.4.18; + + +/* + +Temporary Hash Registrar +======================== + +This is a simplified version of a hash registrar. It is purporsefully limited: +names cannot be six letters or shorter, new auctions will stop after 4 years. + +The plan is to test the basic features and then move to a new contract in at most +2 years, when some sort of renewal mechanism will be enabled. +*/ + + +import './ENS.sol'; +import './Deed.sol'; + +/** + * @title Registrar + * @dev The registrar handles the auction process for each subnode of the node it owns. + */ +contract Registrar { + ENS public ens; + bytes32 public rootNode; + + mapping (bytes32 => Entry) _entries; + mapping (address => mapping (bytes32 => Deed)) public sealedBids; + + enum Mode { Open, Auction, Owned, Forbidden, Reveal, NotYetAvailable } + + uint32 constant totalAuctionLength = 5 days; + uint32 constant revealPeriod = 48 hours; + uint32 public constant launchLength = 8 weeks; + + uint constant minPrice = 0.01 ether; + uint public registryStarted; + + event AuctionStarted(bytes32 indexed hash, uint registrationDate); + event NewBid(bytes32 indexed hash, address indexed bidder, uint deposit); + event BidRevealed(bytes32 indexed hash, address indexed owner, uint value, uint8 status); + event HashRegistered(bytes32 indexed hash, address indexed owner, uint value, uint registrationDate); + event HashReleased(bytes32 indexed hash, uint value); + event HashInvalidated(bytes32 indexed hash, string indexed name, uint value, uint registrationDate); + + struct Entry { + Deed deed; + uint registrationDate; + uint value; + uint highestBid; + } + + modifier inState(bytes32 _hash, Mode _state) { + require(state(_hash) == _state); + _; + } + + modifier onlyOwner(bytes32 _hash) { + require(state(_hash) == Mode.Owned && msg.sender == _entries[_hash].deed.owner()); + _; + } + + modifier registryOpen() { + require(now >= registryStarted && now <= registryStarted + 4 years && ens.owner(rootNode) == address(this)); + _; + } + + /** + * @dev Constructs a new Registrar, with the provided address as the owner of the root node. + * + * @param _ens The address of the ENS + * @param _rootNode The hash of the rootnode. + */ + function Registrar(ENS _ens, bytes32 _rootNode, uint _startDate) public { + ens = _ens; + rootNode = _rootNode; + registryStarted = _startDate > 0 ? _startDate : now; + } + + /** + * @dev Start an auction for an available hash + * + * @param _hash The hash to start an auction on + */ + function startAuction(bytes32 _hash) public registryOpen() { + Mode mode = state(_hash); + if (mode == Mode.Auction) return; + require(mode == Mode.Open); + + Entry storage newAuction = _entries[_hash]; + newAuction.registrationDate = now + totalAuctionLength; + newAuction.value = 0; + newAuction.highestBid = 0; + AuctionStarted(_hash, newAuction.registrationDate); + } + + /** + * @dev Start multiple auctions for better anonymity + * + * Anyone can start an auction by sending an array of hashes that they want to bid for. + * Arrays are sent so that someone can open up an auction for X dummy hashes when they + * are only really interested in bidding for one. This will increase the cost for an + * attacker to simply bid blindly on all new auctions. Dummy auctions that are + * open but not bid on are closed after a week. + * + * @param _hashes An array of hashes, at least one of which you presumably want to bid on + */ + function startAuctions(bytes32[] _hashes) public { + for (uint i = 0; i < _hashes.length; i ++) { + startAuction(_hashes[i]); + } + } + + /** + * @dev Submit a new sealed bid on a desired hash in a blind auction + * + * Bids are sent by sending a message to the main contract with a hash and an amount. The hash + * contains information about the bid, including the bidded hash, the bid amount, and a random + * salt. Bids are not tied to any one auction until they are revealed. The value of the bid + * itself can be masqueraded by sending more than the value of your actual bid. This is + * followed by a 48h reveal period. Bids revealed after this period will be burned and the ether unrecoverable. + * Since this is an auction, it is expected that most public hashes, like known domains and common dictionary + * words, will have multiple bidders pushing the price up. + * + * @param sealedBid A sealedBid, created by the shaBid function + */ + function newBid(bytes32 sealedBid) public payable { + require(address(sealedBids[msg.sender][sealedBid]) == 0x0); + require(msg.value >= minPrice); + + // Creates a new hash contract with the owner + Deed newBid = (new Deed).value(msg.value)(msg.sender); + sealedBids[msg.sender][sealedBid] = newBid; + NewBid(sealedBid, msg.sender, msg.value); + } + + /** + * @dev Start a set of auctions and bid on one of them + * + * This method functions identically to calling `startAuctions` followed by `newBid`, + * but all in one transaction. + * + * @param hashes A list of hashes to start auctions on. + * @param sealedBid A sealed bid for one of the auctions. + */ + function startAuctionsAndBid(bytes32[] hashes, bytes32 sealedBid) public payable { + startAuctions(hashes); + newBid(sealedBid); + } + + /** + * @dev Submit the properties of a bid to reveal them + * + * @param _hash The node in the sealedBid + * @param _value The bid amount in the sealedBid + * @param _salt The sale in the sealedBid + */ + function unsealBid(bytes32 _hash, uint _value, bytes32 _salt) public { + bytes32 seal = shaBid(_hash, msg.sender, _value, _salt); + Deed bid = sealedBids[msg.sender][seal]; + require(address(bid) != 0); + + sealedBids[msg.sender][seal] = Deed(0); + Entry storage h = _entries[_hash]; + uint value = min(_value, bid.value()); + bid.setBalance(value, true); + + var auctionState = state(_hash); + if (auctionState == Mode.Owned) { + // Too late! Bidder loses their bid. Gets 0.5% back. + bid.closeDeed(5); + BidRevealed(_hash, msg.sender, value, 1); + } else if (auctionState != Mode.Reveal) { + // Invalid phase + revert(); + } else if (value < minPrice || bid.creationDate() > h.registrationDate - revealPeriod) { + // Bid too low or too late, refund 99.5% + bid.closeDeed(995); + BidRevealed(_hash, msg.sender, value, 0); + } else if (value > h.highestBid) { + // New winner + // Cancel the other bid, refund 99.5% + if (address(h.deed) != 0) { + Deed previousWinner = h.deed; + previousWinner.closeDeed(995); + } + + // Set new winner + // Per the rules of a vickery auction, the value becomes the previous highestBid + h.value = h.highestBid; // will be zero if there's only 1 bidder + h.highestBid = value; + h.deed = bid; + BidRevealed(_hash, msg.sender, value, 2); + } else if (value > h.value) { + // Not winner, but affects second place + h.value = value; + bid.closeDeed(995); + BidRevealed(_hash, msg.sender, value, 3); + } else { + // Bid doesn't affect auction + bid.closeDeed(995); + BidRevealed(_hash, msg.sender, value, 4); + } + } + + /** + * @dev Cancel a bid + * + * @param seal The value returned by the shaBid function + */ + function cancelBid(address bidder, bytes32 seal) public { + Deed bid = sealedBids[bidder][seal]; + + // If a sole bidder does not `unsealBid` in time, they have a few more days + // where they can call `startAuction` (again) and then `unsealBid` during + // the revealPeriod to get back their bid value. + // For simplicity, they should call `startAuction` within + // 9 days (2 weeks - totalAuctionLength), otherwise their bid will be + // cancellable by anyone. + require(address(bid) != 0 && now >= bid.creationDate() + totalAuctionLength + 2 weeks); + + // Send the canceller 0.5% of the bid, and burn the rest. + bid.setOwner(msg.sender); + bid.closeDeed(5); + sealedBids[bidder][seal] = Deed(0); + BidRevealed(seal, bidder, 0, 5); + } + + /** + * @dev Finalize an auction after the registration date has passed + * + * @param _hash The hash of the name the auction is for + */ + function finalizeAuction(bytes32 _hash) public onlyOwner(_hash) { + Entry storage h = _entries[_hash]; + + // Handles the case when there's only a single bidder (h.value is zero) + h.value = max(h.value, minPrice); + h.deed.setBalance(h.value, true); + + trySetSubnodeOwner(_hash, h.deed.owner()); + HashRegistered(_hash, h.deed.owner(), h.value, h.registrationDate); + } + + /** + * @dev The owner of a domain may transfer it to someone else at any time. + * + * @param _hash The node to transfer + * @param newOwner The address to transfer ownership to + */ + function transfer(bytes32 _hash, address newOwner) public onlyOwner(_hash) { + require(newOwner != 0); + + Entry storage h = _entries[_hash]; + h.deed.setOwner(newOwner); + trySetSubnodeOwner(_hash, newOwner); + } + + /** + * @dev After some time, or if we're no longer the registrar, the owner can release + * the name and get their ether back. + * + * @param _hash The node to release + */ + function releaseDeed(bytes32 _hash) public onlyOwner(_hash) { + Entry storage h = _entries[_hash]; + Deed deedContract = h.deed; + + require(now >= h.registrationDate + 1 years || ens.owner(rootNode) != address(this)); + + h.value = 0; + h.highestBid = 0; + h.deed = Deed(0); + + _tryEraseSingleNode(_hash); + deedContract.closeDeed(1000); + HashReleased(_hash, h.value); + } + + /** + * @dev Submit a name 6 characters long or less. If it has been registered, + * the submitter will earn 50% of the deed value. + * + * We are purposefully handicapping the simplified registrar as a way + * to force it into being restructured in a few years. + * + * @param unhashedName An invalid name to search for in the registry. + */ + function invalidateName(string unhashedName) public inState(keccak256(unhashedName), Mode.Owned) { + require(strlen(unhashedName) <= 6); + bytes32 hash = keccak256(unhashedName); + + Entry storage h = _entries[hash]; + + _tryEraseSingleNode(hash); + + if (address(h.deed) != 0) { + // Reward the discoverer with 50% of the deed + // The previous owner gets 50% + h.value = max(h.value, minPrice); + h.deed.setBalance(h.value/2, false); + h.deed.setOwner(msg.sender); + h.deed.closeDeed(1000); + } + + HashInvalidated(hash, unhashedName, h.value, h.registrationDate); + + h.value = 0; + h.highestBid = 0; + h.deed = Deed(0); + } + + /** + * @dev Allows anyone to delete the owner and resolver records for a (subdomain of) a + * name that is not currently owned in the registrar. If passing, eg, 'foo.bar.eth', + * the owner and resolver fields on 'foo.bar.eth' and 'bar.eth' will all be cleared. + * + * @param labels A series of label hashes identifying the name to zero out, rooted at the + * registrar's root. Must contain at least one element. For instance, to zero + * 'foo.bar.eth' on a registrar that owns '.eth', pass an array containing + * [keccak256('foo'), keccak256('bar')]. + */ + function eraseNode(bytes32[] labels) public { + require(labels.length != 0); + require(state(labels[labels.length - 1]) != Mode.Owned); + + _eraseNodeHierarchy(labels.length - 1, labels, rootNode); + } + + /** + * @dev Transfers the deed to the current registrar, if different from this one. + * + * Used during the upgrade process to a permanent registrar. + * + * @param _hash The name hash to transfer. + */ + function transferRegistrars(bytes32 _hash) public onlyOwner(_hash) { + address registrar = ens.owner(rootNode); + require(registrar != address(this)); + + // Migrate the deed + Entry storage h = _entries[_hash]; + h.deed.setRegistrar(registrar); + + // Call the new registrar to accept the transfer + Registrar(registrar).acceptRegistrarTransfer(_hash, h.deed, h.registrationDate); + + // Zero out the Entry + h.deed = Deed(0); + h.registrationDate = 0; + h.value = 0; + h.highestBid = 0; + } + + /** + * @dev Accepts a transfer from a previous registrar; stubbed out here since there + * is no previous registrar implementing this interface. + * + * @param hash The sha3 hash of the label to transfer. + * @param deed The Deed object for the name being transferred in. + * @param registrationDate The date at which the name was originally registered. + */ + function acceptRegistrarTransfer(bytes32 hash, Deed deed, uint registrationDate) public { + hash; deed; registrationDate; // Don't warn about unused variables + } + + // State transitions for names: + // Open -> Auction (startAuction) + // Auction -> Reveal + // Reveal -> Owned + // Reveal -> Open (if nobody bid) + // Owned -> Open (releaseDeed or invalidateName) + function state(bytes32 _hash) public view returns (Mode) { + Entry storage entry = _entries[_hash]; + + if (!isAllowed(_hash, now)) { + return Mode.NotYetAvailable; + } else if (now < entry.registrationDate) { + if (now < entry.registrationDate - revealPeriod) { + return Mode.Auction; + } else { + return Mode.Reveal; + } + } else { + if (entry.highestBid == 0) { + return Mode.Open; + } else { + return Mode.Owned; + } + } + } + + function entries(bytes32 _hash) public view returns (Mode, address, uint, uint, uint) { + Entry storage h = _entries[_hash]; + return (state(_hash), h.deed, h.registrationDate, h.value, h.highestBid); + } + + /** + * @dev Determines if a name is available for registration yet + * + * Each name will be assigned a random date in which its auction + * can be started, from 0 to 8 weeks + * + * @param _hash The hash to start an auction on + * @param _timestamp The timestamp to query about + */ + function isAllowed(bytes32 _hash, uint _timestamp) public view returns (bool allowed) { + return _timestamp > getAllowedTime(_hash); + } + + /** + * @dev Returns available date for hash + * + * The available time from the `registryStarted` for a hash is proportional + * to its numeric value. + * + * @param _hash The hash to start an auction on + */ + function getAllowedTime(bytes32 _hash) public view returns (uint) { + return registryStarted + ((launchLength * (uint(_hash) >> 128)) >> 128); + // Right shift operator: a >> b == a / 2**b + } + + /** + * @dev Hash the values required for a secret bid + * + * @param hash The node corresponding to the desired namehash + * @param value The bid amount + * @param salt A random value to ensure secrecy of the bid + * @return The hash of the bid values + */ + function shaBid(bytes32 hash, address owner, uint value, bytes32 salt) public pure returns (bytes32) { + return keccak256(hash, owner, value, salt); + } + + function _tryEraseSingleNode(bytes32 label) internal { + if (ens.owner(rootNode) == address(this)) { + ens.setSubnodeOwner(rootNode, label, address(this)); + bytes32 node = keccak256(rootNode, label); + ens.setResolver(node, 0); + ens.setOwner(node, 0); + } + } + + function _eraseNodeHierarchy(uint idx, bytes32[] labels, bytes32 node) internal { + // Take ownership of the node + ens.setSubnodeOwner(node, labels[idx], address(this)); + node = keccak256(node, labels[idx]); + + // Recurse if there are more labels + if (idx > 0) { + _eraseNodeHierarchy(idx - 1, labels, node); + } + + // Erase the resolver and owner records + ens.setResolver(node, 0); + ens.setOwner(node, 0); + } + + /** + * @dev Assign the owner in ENS, if we're still the registrar + * + * @param _hash hash to change owner + * @param _newOwner new owner to transfer to + */ + function trySetSubnodeOwner(bytes32 _hash, address _newOwner) internal { + if (ens.owner(rootNode) == address(this)) + ens.setSubnodeOwner(rootNode, _hash, _newOwner); + } + + /** + * @dev Returns the maximum of two unsigned integers + * + * @param a A number to compare + * @param b A number to compare + * @return The maximum of two unsigned integers + */ + function max(uint a, uint b) internal pure returns (uint) { + if (a > b) + return a; + else + return b; + } + + /** + * @dev Returns the minimum of two unsigned integers + * + * @param a A number to compare + * @param b A number to compare + * @return The minimum of two unsigned integers + */ + function min(uint a, uint b) internal pure returns (uint) { + if (a < b) + return a; + else + return b; + } + + /** + * @dev Returns the length of a given string + * + * @param s The string to measure the length of + * @return The length of the input string + */ + function strlen(string s) internal pure returns (uint) { + s; // Don't warn about unused variables + // Starting here means the LSB will be the byte we care about + uint ptr; + uint end; + assembly { + ptr := add(s, 1) + end := add(mload(s), ptr) + } + for (uint len = 0; ptr < end; len++) { + uint8 b; + assembly { b := and(mload(ptr), 0xFF) } + if (b < 0x80) { + ptr += 1; + } else if (b < 0xE0) { + ptr += 2; + } else if (b < 0xF0) { + ptr += 3; + } else if (b < 0xF8) { + ptr += 4; + } else if (b < 0xFC) { + ptr += 5; + } else { + ptr += 6; + } + } + return len; + } + +} diff --git a/lib/modules/ens/contracts/PublicResolver.sol b/lib/modules/ens/contracts/PublicResolver.sol new file mode 100644 index 000000000..1d02357d0 --- /dev/null +++ b/lib/modules/ens/contracts/PublicResolver.sol @@ -0,0 +1,238 @@ +pragma solidity ^0.4.18; + +import './ENS.sol'; + +/** + * A simple resolver anyone can use; only allows the owner of a node to set its + * address. + */ +contract PublicResolver { + + bytes4 constant INTERFACE_META_ID = 0x01ffc9a7; + bytes4 constant ADDR_INTERFACE_ID = 0x3b3b57de; + bytes4 constant CONTENT_INTERFACE_ID = 0xd8389dc5; + bytes4 constant NAME_INTERFACE_ID = 0x691f3431; + bytes4 constant ABI_INTERFACE_ID = 0x2203ab56; + bytes4 constant PUBKEY_INTERFACE_ID = 0xc8690233; + bytes4 constant TEXT_INTERFACE_ID = 0x59d1d43c; + bytes4 constant MULTIHASH_INTERFACE_ID = 0xe89401a1; + + 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); + event MultihashChanged(bytes32 indexed node, bytes hash); + + struct PublicKey { + bytes32 x; + bytes32 y; + } + + struct Record { + address addr; + bytes32 content; + string name; + PublicKey pubkey; + mapping(string=>string) text; + mapping(uint256=>bytes) abis; + bytes multihash; + } + + ENS ens; + + mapping (bytes32 => Record) records; + + modifier only_owner(bytes32 node) { + require(ens.owner(node) == msg.sender); + _; + } + + /** + * Constructor. + * @param ensAddr The ENS registrar contract. + */ + function PublicResolver(ENS ensAddr) public { + ens = ensAddr; + } + + /** + * 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; + AddrChanged(node, addr); + } + + /** + * 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; + ContentChanged(node, hash); + } + + /** + * Sets the multihash 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 hash The multihash to set + */ + function setMultihash(bytes32 node, bytes hash) public only_owner(node) { + records[node].multihash = hash; + MultihashChanged(node, hash); + } + + /** + * 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; + 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; + 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); + 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; + 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 multihash associated with an ENS node. + * @param node The ENS node to query. + * @return The associated multihash. + */ + function multihash(bytes32 node) public view returns (bytes) { + return records[node].multihash; + } + + /** + * 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; + } + + /** + * Returns true if the resolver implements the interface specified by the provided hash. + * @param interfaceID The ID of the interface to check for. + * @return True if the contract implements the requested interface. + */ + function supportsInterface(bytes4 interfaceID) public pure returns (bool) { + return interfaceID == ADDR_INTERFACE_ID || + interfaceID == CONTENT_INTERFACE_ID || + interfaceID == NAME_INTERFACE_ID || + interfaceID == ABI_INTERFACE_ID || + interfaceID == PUBKEY_INTERFACE_ID || + interfaceID == TEXT_INTERFACE_ID || + interfaceID == MULTIHASH_INTERFACE_ID || + interfaceID == INTERFACE_META_ID; + } +} diff --git a/lib/modules/ens/contracts/ResolverInterface.sol b/lib/modules/ens/contracts/ResolverInterface.sol new file mode 100644 index 000000000..006bf2013 --- /dev/null +++ b/lib/modules/ens/contracts/ResolverInterface.sol @@ -0,0 +1,10 @@ +pragma solidity ^0.4.18; + +contract ResolverInterface { + function PublicResolver(address ensAddr) public; + function setAddr(bytes32 node, address addr) public; + function setHash(bytes32 node, bytes32 hash) public; + function addr(bytes32 node) public view returns (address); + function hash(bytes32 node) public view returns (bytes32); + function supportsInterface(bytes4 interfaceID) public pure returns (bool); +} diff --git a/lib/modules/ens/contracts/ReverseRegistrar.sol b/lib/modules/ens/contracts/ReverseRegistrar.sol new file mode 100644 index 000000000..d30557292 --- /dev/null +++ b/lib/modules/ens/contracts/ReverseRegistrar.sol @@ -0,0 +1,117 @@ +pragma solidity ^0.4.10; + +import "./ENS.sol"; + +contract Resolver { + function setName(bytes32 node, string name) public; +} + +contract ReverseRegistrar { + // namehash('addr.reverse') + bytes32 constant ADDR_REVERSE_NODE = 0x91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e2; + + ENS public ens; + Resolver public defaultResolver; + + /** + * @dev Constructor + * @param ensAddr The address of the ENS registry. + * @param resolverAddr The address of the default reverse resolver. + */ + function ReverseRegistrar(ENS ensAddr, Resolver resolverAddr) public { + ens = ensAddr; + defaultResolver = resolverAddr; + + // Assign ownership of the reverse record to our deployer + ReverseRegistrar oldRegistrar = ReverseRegistrar(ens.owner(ADDR_REVERSE_NODE)); + if (address(oldRegistrar) != 0) { + oldRegistrar.claim(msg.sender); + } + } + + /** + * @dev Transfers ownership of the reverse ENS record associated with the + * calling account. + * @param owner The address to set as the owner of the reverse record in ENS. + * @return The ENS node hash of the reverse record. + */ + function claim(address owner) public returns (bytes32) { + return claimWithResolver(owner, 0); + } + + /** + * @dev Transfers ownership of the reverse ENS record associated with the + * calling account. + * @param owner The address to set as the owner of the reverse record in ENS. + * @param resolver The address of the resolver to set; 0 to leave unchanged. + * @return The ENS node hash of the reverse record. + */ + function claimWithResolver(address owner, address resolver) public returns (bytes32) { + var label = sha3HexAddress(msg.sender); + bytes32 node = keccak256(ADDR_REVERSE_NODE, label); + var currentOwner = ens.owner(node); + + // Update the resolver if required + if (resolver != 0 && resolver != ens.resolver(node)) { + // Transfer the name to us first if it's not already + if (currentOwner != address(this)) { + ens.setSubnodeOwner(ADDR_REVERSE_NODE, label, this); + currentOwner = address(this); + } + ens.setResolver(node, resolver); + } + + // Update the owner if required + if (currentOwner != owner) { + ens.setSubnodeOwner(ADDR_REVERSE_NODE, label, owner); + } + + return node; + } + + /** + * @dev Sets the `name()` record for the reverse ENS record associated with + * the calling account. First updates the resolver to the default reverse + * resolver if necessary. + * @param name The name to set for this address. + * @return The ENS node hash of the reverse record. + */ + function setName(string name) public returns (bytes32) { + bytes32 node = claimWithResolver(this, defaultResolver); + defaultResolver.setName(node, name); + return node; + } + + /** + * @dev Returns the node hash for a given account's reverse records. + * @param addr The address to hash + * @return The ENS node hash. + */ + function node(address addr) public view returns (bytes32) { + return keccak256(ADDR_REVERSE_NODE, sha3HexAddress(addr)); + } + + /** + * @dev An optimised function to compute the sha3 of the lower-case + * hexadecimal representation of an Ethereum address. + * @param addr The address to hash + * @return The SHA3 hash of the lower-case hexadecimal encoding of the + * input address. + */ + function sha3HexAddress(address addr) private returns (bytes32 ret) { + addr; ret; // Stop warning us about unused variables + assembly { + let lookup := 0x3031323334353637383961626364656600000000000000000000000000000000 + let i := 40 + loop: + i := sub(i, 1) + mstore8(i, byte(and(addr, 0xf), lookup)) + addr := div(addr, 0x10) + i := sub(i, 1) + mstore8(i, byte(and(addr, 0xf), lookup)) + addr := div(addr, 0x10) + jumpi(loop, i) + ret := keccak256(0, 40) + } + } +} diff --git a/lib/modules/ens/contracts/TestRegistrar.sol b/lib/modules/ens/contracts/TestRegistrar.sol new file mode 100644 index 000000000..c46421eeb --- /dev/null +++ b/lib/modules/ens/contracts/TestRegistrar.sol @@ -0,0 +1,37 @@ +pragma solidity ^0.4.18; + +import './ENS.sol'; + +/** + * A registrar that allocates subdomains to the first person to claim them, but + * expires registrations a fixed period after they're initially claimed. + */ +contract TestRegistrar { + uint constant registrationPeriod = 4 weeks; + + ENS public ens; + bytes32 public rootNode; + mapping (bytes32 => uint) public expiryTimes; + + /** + * Constructor. + * @param ensAddr The address of the ENS registry. + * @param node The node that this registrar administers. + */ + function TestRegistrar(ENS ensAddr, bytes32 node) public { + ens = ensAddr; + rootNode = node; + } + + /** + * Register a name that's not currently registered + * @param subnode The hash of the label to register. + * @param owner The address of the new owner. + */ + function register(bytes32 subnode, address owner) public { + require(expiryTimes[subnode] < now); + + expiryTimes[subnode] = now + registrationPeriod; + ens.setSubnodeOwner(rootNode, subnode, owner); + } +} From e8d55bdb0dede751b31f7ceb01298c6461b0e153 Mon Sep 17 00:00:00 2001 From: VoR0220 Date: Fri, 15 Jun 2018 10:23:55 -0500 Subject: [PATCH 02/17] attempt at deploying on dev net Signed-off-by: VoR0220 --- lib/modules/ens/embarkjs.js | 119 +----------------------------------- lib/modules/ens/index.js | 41 ++++++++++++- 2 files changed, 43 insertions(+), 117 deletions(-) diff --git a/lib/modules/ens/embarkjs.js b/lib/modules/ens/embarkjs.js index 1f37856cf..447d04e5a 100644 --- a/lib/modules/ens/embarkjs.js +++ b/lib/modules/ens/embarkjs.js @@ -3,96 +3,7 @@ import namehash from 'eth-ens-namehash'; /*global web3*/ let __embarkENS = {}; -// registry interface for later -__embarkENS.registryInterface = [ - { - "constant": true, - "inputs": [ - { - "name": "node", - "type": "bytes32" - } - ], - "name": "resolver", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "node", - "type": "bytes32" - } - ], - "name": "owner", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "node", - "type": "bytes32" - }, - { - "name": "resolver", - "type": "address" - } - ], - "name": "setResolver", - "outputs": [], - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "node", - "type": "bytes32" - }, - { - "name": "label", - "type": "bytes32" - }, - { - "name": "owner", - "type": "address" - } - ], - "name": "setSubnodeOwner", - "outputs": [], - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "node", - "type": "bytes32" - }, - { - "name": "owner", - "type": "address" - } - ], - "name": "setOwner", - "outputs": [], - "type": "function" - } -]; - +// resolver interface __embarkENS.resolverInterface = [ { "constant": true, @@ -242,32 +153,8 @@ __embarkENS.resolverInterface = [ } ]; -__embarkENS.registryAddresses = { - // Mainnet - "1": "0x314159265dd8dbb310642f98f50c066173c1259b", - // Ropsten - "3": "0x112234455c3a32fd11230c42e7bccd4a84e02010", - // Rinkeby - "4": "0xe7410170f87102DF0055eB195163A03B7F2Bff4A" -}; - -__embarkENS.setProvider = function () { - const self = this; - // get network id and then assign ENS contract based on that - let registryAddresses = this.registryAddresses; - this.ens = null; - web3.eth.net.getId().then(id => { - if (registryAddresses[id] !== undefined) { - self.ens = new web3.eth.Contract(self.registryInterface, registryAddresses[id]); - } - // todo: deploy at this point - }).catch(e => { - if (e.message.indexOf('Provider not set or invalid') > -1) { - console.warn('ENS is not available in this chain'); - return; - } - console.error(e); - }); +__embarkENS.setProvider = function (jsonObject) { + this.ens = JSON.parse(jsonObject); }; __embarkENS.resolve = function(name) { diff --git a/lib/modules/ens/index.js b/lib/modules/ens/index.js index 0b0c66569..56e60268f 100644 --- a/lib/modules/ens/index.js +++ b/lib/modules/ens/index.js @@ -1,3 +1,4 @@ +/*global web3*/ const fs = require('../../core/fs.js'); const utils = require('../../utils/utils.js'); @@ -7,6 +8,8 @@ class ENS { this.events = embark.events; this.namesConfig = embark.config.namesystemConfig; this.embark = embark; + this.ensRegistry = null; + this.ensResolver = null; this.addENSToEmbarkJS(); this.addSetProvider(); @@ -23,6 +26,7 @@ class ENS { return; } + // get namehash, import it into file self.events.request("version:get:eth-ens-namehash", function(EnsNamehashVersion) { let currentEnsNamehashVersion = require('../../../package.json').dependencies["eth-ens-namehash"]; if (EnsNamehashVersion !== currentEnsNamehashVersion) { @@ -39,8 +43,43 @@ class ENS { this.embark.addCodeToEmbarkJS(code); } + configureENSRegistry() { + const self = this; + self.embark.addContractFile('./contracts/ENSRegistry.sol'); + self.embark.registerContractConfiguration({ + "default": { + "gas": "auto", + "ENSRegistry": { + "deploy": true, + } + }, + "ropsten": { + "ENSRegistry": { + "address": "0x112234455c3a32fd11230c42e7bccd4a84e02010" + } + }, + "rinkeby": { + "ENSRegistry": { + "address": "0xe7410170f87102DF0055eB195163A03B7F2Bff4A" + } + }, + "mainnet": { + "ENSRegistry": { + "address": "0x314159265dd8dbb310642f98f50c066173c1259b" + } + } + }); + self.events.on("deploy:contract:deployed", (contract) => { + if (contract.className === "ENSRegistry") { + return web3.eth.Contract(contract.abiDefinition, contract.address); + } + }) + } + addSetProvider() { - let config = JSON.stringify({}); + const self = this; + + let config = JSON.stringify(self.configureENSRegistry()); let code = "\nEmbarkJS.Names.setProvider('ens'," + config + ");"; From fb899ea3be7ef1c70af9c63e85d4b8787e2da5f2 Mon Sep 17 00:00:00 2001 From: VoR0220 Date: Fri, 15 Jun 2018 10:24:13 -0500 Subject: [PATCH 03/17] package lock Signed-off-by: VoR0220 --- package-lock.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/package-lock.json b/package-lock.json index 02c091ca4..bc19d9d2d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8043,6 +8043,11 @@ "resolved": "https://registry.npmjs.org/mime.json/-/mime.json-1.0.18.tgz", "integrity": "sha512-GA+bgKycQECTUKDszphjkhKO7N6frDyrWTH4mZ2W9ohFYxT0U2pkN0+XzvBU8LSRzyQLvmDK2bBpXmPfLbckWw==" }, + "mime.json": { + "version": "1.0.18", + "resolved": "https://registry.npmjs.org/mime.json/-/mime.json-1.0.18.tgz", + "integrity": "sha512-GA+bgKycQECTUKDszphjkhKO7N6frDyrWTH4mZ2W9ohFYxT0U2pkN0+XzvBU8LSRzyQLvmDK2bBpXmPfLbckWw==" + }, "mimic-fn": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", From dc71b1725a5187e7e2b422e6b31543f4ea2473bd Mon Sep 17 00:00:00 2001 From: VoR0220 Date: Fri, 15 Jun 2018 10:59:55 -0500 Subject: [PATCH 04/17] lint is lyfe Signed-off-by: VoR0220 --- lib/modules/ens/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/modules/ens/index.js b/lib/modules/ens/index.js index 56e60268f..450b6e462 100644 --- a/lib/modules/ens/index.js +++ b/lib/modules/ens/index.js @@ -50,7 +50,7 @@ class ENS { "default": { "gas": "auto", "ENSRegistry": { - "deploy": true, + "deploy": true } }, "ropsten": { @@ -73,7 +73,7 @@ class ENS { if (contract.className === "ENSRegistry") { return web3.eth.Contract(contract.abiDefinition, contract.address); } - }) + }); } addSetProvider() { From 6de3274fa6191bafb03e706ec6cb0f9974a49e3c Mon Sep 17 00:00:00 2001 From: VoR0220 Date: Fri, 15 Jun 2018 12:32:48 -0500 Subject: [PATCH 05/17] starting to create registration and some changes to the deployment Signed-off-by: VoR0220 --- js/embark.js | 8 +++++--- lib/modules/ens/embarkjs.js | 36 +++++++++++++++++++++++++++++++----- lib/modules/ens/index.js | 20 +++++++++++--------- 3 files changed, 47 insertions(+), 17 deletions(-) diff --git a/js/embark.js b/js/embark.js index cff85842a..cf2fae889 100644 --- a/js/embark.js +++ b/js/embark.js @@ -376,12 +376,14 @@ EmbarkJS.Names.lookup = function (identifier) { // To Implement -/* + // register a name EmbarkJS.Names.register = function(name, options) { - + if (!this.currentNameSystems) { + throw new Error('Name system provider not set; e.g EmbarkJS.Names.setProvider("ens")'); + } + return this.currentNameSystems.register(name, options); } -*/ EmbarkJS.Utils = { fromAscii: function (str) { diff --git a/lib/modules/ens/embarkjs.js b/lib/modules/ens/embarkjs.js index 447d04e5a..f912baac2 100644 --- a/lib/modules/ens/embarkjs.js +++ b/lib/modules/ens/embarkjs.js @@ -153,11 +153,11 @@ __embarkENS.resolverInterface = [ } ]; -__embarkENS.setProvider = function (jsonObject) { - this.ens = JSON.parse(jsonObject); +__embarkENS.setProvider = function (config) { + this.ens = new web3.eth.Contract(config.abi, config.address); }; -__embarkENS.resolve = function(name) { +__embarkENS.resolve = function (name) { const self = this; if (self.ens === undefined) return; @@ -172,7 +172,7 @@ __embarkENS.resolve = function(name) { }).catch(err => err); }; -__embarkENS.lookup = function(address) { +__embarkENS.lookup = function (address) { const self = this; if (self.ens === undefined) return; @@ -185,7 +185,33 @@ __embarkENS.lookup = function(address) { let resolverContract = new web3.eth.Contract(self.resolverInterface, resolverAddress); return resolverContract.methods.name(node).call(); }).then((name) => { - if (name === "" || name === undefined) throw Error("ENS name not found"); + if (name === "" || name === undefined) { + console.warn("ENS name not found"); + return; + } return name; }).catch(err => err); }; + +__embarkENS.register = function (name, options) { + const self = this; + + if (self.ens === undefined) return; + + if (options.livenet) { + return; + } + + let node = namehash.hash(name); + + return self.ens.methods.owner(node).call().then((owner) => { + if (owner !== "0x" || owner !== undefined) { + console.warn("name has already been claimed, see owner: ", owner); + return; + } + return self.ens.methods.setSubnodeOwner(node, ); + }).then((addr) => { + + return addr; + }).catch(err => err); +} diff --git a/lib/modules/ens/index.js b/lib/modules/ens/index.js index 450b6e462..6d1336ccb 100644 --- a/lib/modules/ens/index.js +++ b/lib/modules/ens/index.js @@ -4,6 +4,7 @@ const utils = require('../../utils/utils.js'); class ENS { constructor(embark, _options) { + const self = this; this.logger = embark.logger; this.events = embark.events; this.namesConfig = embark.config.namesystemConfig; @@ -12,7 +13,12 @@ class ENS { this.ensResolver = null; this.addENSToEmbarkJS(); - this.addSetProvider(); + this.configureENSRegistry((abi, addr) => { + self.addSetProvider({ + abi: abi, + address: addr + }); + }); } addENSToEmbarkJS() { @@ -43,7 +49,7 @@ class ENS { this.embark.addCodeToEmbarkJS(code); } - configureENSRegistry() { + configureENSRegistry(cb) { const self = this; self.embark.addContractFile('./contracts/ENSRegistry.sol'); self.embark.registerContractConfiguration({ @@ -69,18 +75,14 @@ class ENS { } } }); - self.events.on("deploy:contract:deployed", (contract) => { + self.events.on("contracts:deploy:afterAll", (contract) => { if (contract.className === "ENSRegistry") { - return web3.eth.Contract(contract.abiDefinition, contract.address); + cb(contract.abiDefinition, contract.address); } }); } - addSetProvider() { - const self = this; - - let config = JSON.stringify(self.configureENSRegistry()); - + addSetProvider(config) { let code = "\nEmbarkJS.Names.setProvider('ens'," + config + ");"; let shouldInit = (namesConfig) => { From 1979d48bb911d36729e8323eaa0666ea44b50e70 Mon Sep 17 00:00:00 2001 From: VoR0220 Date: Sat, 16 Jun 2018 07:44:44 -0500 Subject: [PATCH 06/17] temp commit Signed-off-by: VoR0220 --- lib/modules/ens/embarkjs.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/modules/ens/embarkjs.js b/lib/modules/ens/embarkjs.js index f912baac2..4d91b9808 100644 --- a/lib/modules/ens/embarkjs.js +++ b/lib/modules/ens/embarkjs.js @@ -193,7 +193,7 @@ __embarkENS.lookup = function (address) { }).catch(err => err); }; -__embarkENS.register = function (name, options) { +/*__embarkENS.register = function (name, options) { const self = this; if (self.ens === undefined) return; @@ -214,4 +214,4 @@ __embarkENS.register = function (name, options) { return addr; }).catch(err => err); -} +}*/ From 417b5145a4760191ea2113b434def2eff6b1b462 Mon Sep 17 00:00:00 2001 From: VoR0220 Date: Mon, 18 Jun 2018 10:45:20 -0500 Subject: [PATCH 07/17] add in new api for ens Signed-off-by: VoR0220 --- lib/modules/ens/index.js | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/lib/modules/ens/index.js b/lib/modules/ens/index.js index 6d1336ccb..09d889d0a 100644 --- a/lib/modules/ens/index.js +++ b/lib/modules/ens/index.js @@ -13,10 +13,16 @@ class ENS { this.ensResolver = null; this.addENSToEmbarkJS(); - this.configureENSRegistry((abi, addr) => { - self.addSetProvider({ - abi: abi, - address: addr + this.configureENSRegistry(); + self.embark.registerActionForEvent("contracts:deploy:afterAll", (cb) => { + self.events.request('contracts:contract', "ENSRegistry", (contract) => { + console.log("CONTRACT: ", contract); + /*let config = { + abi: contract.abiDefinition, + address: contract.deployedAddress + };*/ + //self.addSetProvider(config); + return cb(); }); }); } @@ -49,40 +55,41 @@ class ENS { this.embark.addCodeToEmbarkJS(code); } - configureENSRegistry(cb) { + configureENSRegistry() { const self = this; - self.embark.addContractFile('./contracts/ENSRegistry.sol'); + console.log("DIS DIR RIGHT HEYA: ", __dirname); self.embark.registerContractConfiguration({ "default": { "gas": "auto", "ENSRegistry": { - "deploy": true + "deploy": true, + "args": [] } }, "ropsten": { "ENSRegistry": { - "address": "0x112234455c3a32fd11230c42e7bccd4a84e02010" + "address": "0x112234455c3a32fd11230c42e7bccd4a84e02010", + "args": [] } }, "rinkeby": { "ENSRegistry": { - "address": "0xe7410170f87102DF0055eB195163A03B7F2Bff4A" + "address": "0xe7410170f87102DF0055eB195163A03B7F2Bff4A", + "args": [] } }, - "mainnet": { + "livenet": { "ENSRegistry": { - "address": "0x314159265dd8dbb310642f98f50c066173c1259b" + "address": "0x314159265dd8dbb310642f98f50c066173c1259b", + "args": [] } } }); - self.events.on("contracts:deploy:afterAll", (contract) => { - if (contract.className === "ENSRegistry") { - cb(contract.abiDefinition, contract.address); - } - }); + self.embark.events.request("config:contractsFiles:add", embark.pathToFile('./contracts/ENSRegistry.sol')); } addSetProvider(config) { + let code = "\nEmbarkJS.Names.setProvider('ens'," + config + ");"; let shouldInit = (namesConfig) => { From 4b8fd88ebca9ad46e7bc45f2ee416f7af89b45c8 Mon Sep 17 00:00:00 2001 From: VoR0220 Date: Mon, 18 Jun 2018 10:58:42 -0500 Subject: [PATCH 08/17] finish the deployment stage Signed-off-by: VoR0220 --- lib/modules/ens/index.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/modules/ens/index.js b/lib/modules/ens/index.js index 09d889d0a..d1345c8ba 100644 --- a/lib/modules/ens/index.js +++ b/lib/modules/ens/index.js @@ -16,12 +16,11 @@ class ENS { this.configureENSRegistry(); self.embark.registerActionForEvent("contracts:deploy:afterAll", (cb) => { self.events.request('contracts:contract', "ENSRegistry", (contract) => { - console.log("CONTRACT: ", contract); - /*let config = { + let config = { abi: contract.abiDefinition, address: contract.deployedAddress - };*/ - //self.addSetProvider(config); + }; + self.addSetProvider(config); return cb(); }); }); @@ -85,7 +84,7 @@ class ENS { } } }); - self.embark.events.request("config:contractsFiles:add", embark.pathToFile('./contracts/ENSRegistry.sol')); + self.embark.events.request("config:contractsFiles:add", self.embark.pathToFile('./contracts/ENSRegistry.sol')); } addSetProvider(config) { From d3f7d0e702c528ee3af682a00fba8c50c5c4e1ff Mon Sep 17 00:00:00 2001 From: VoR0220 Date: Mon, 18 Jun 2018 10:58:50 -0500 Subject: [PATCH 09/17] package lock Signed-off-by: VoR0220 --- package-lock.json | 5 ----- 1 file changed, 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index bc19d9d2d..02c091ca4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8043,11 +8043,6 @@ "resolved": "https://registry.npmjs.org/mime.json/-/mime.json-1.0.18.tgz", "integrity": "sha512-GA+bgKycQECTUKDszphjkhKO7N6frDyrWTH4mZ2W9ohFYxT0U2pkN0+XzvBU8LSRzyQLvmDK2bBpXmPfLbckWw==" }, - "mime.json": { - "version": "1.0.18", - "resolved": "https://registry.npmjs.org/mime.json/-/mime.json-1.0.18.tgz", - "integrity": "sha512-GA+bgKycQECTUKDszphjkhKO7N6frDyrWTH4mZ2W9ohFYxT0U2pkN0+XzvBU8LSRzyQLvmDK2bBpXmPfLbckWw==" - }, "mimic-fn": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", From c568b36977b7b822132ed59f3f37a9ce3fdd19c8 Mon Sep 17 00:00:00 2001 From: VoR0220 Date: Mon, 18 Jun 2018 12:43:52 -0500 Subject: [PATCH 10/17] finish it all up Signed-off-by: VoR0220 --- lib/modules/ens/index.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/modules/ens/index.js b/lib/modules/ens/index.js index d1345c8ba..f0206b8f7 100644 --- a/lib/modules/ens/index.js +++ b/lib/modules/ens/index.js @@ -56,7 +56,6 @@ class ENS { configureENSRegistry() { const self = this; - console.log("DIS DIR RIGHT HEYA: ", __dirname); self.embark.registerContractConfiguration({ "default": { "gas": "auto", @@ -88,8 +87,8 @@ class ENS { } addSetProvider(config) { - - let code = "\nEmbarkJS.Names.setProvider('ens'," + config + ");"; + + let code = "\nEmbarkJS.Names.setProvider('ens'," + JSON.stringify(config) + ");"; let shouldInit = (namesConfig) => { return (namesConfig.provider === 'ens' && namesConfig.enabled === true); From f6fccd4588eab74f61187dbe064ea2592592e904 Mon Sep 17 00:00:00 2001 From: VoR0220 Date: Mon, 18 Jun 2018 12:45:21 -0500 Subject: [PATCH 11/17] get rid of register for now Signed-off-by: VoR0220 --- lib/modules/ens/embarkjs.js | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/lib/modules/ens/embarkjs.js b/lib/modules/ens/embarkjs.js index 4d91b9808..0b549ebde 100644 --- a/lib/modules/ens/embarkjs.js +++ b/lib/modules/ens/embarkjs.js @@ -192,26 +192,3 @@ __embarkENS.lookup = function (address) { return name; }).catch(err => err); }; - -/*__embarkENS.register = function (name, options) { - const self = this; - - if (self.ens === undefined) return; - - if (options.livenet) { - return; - } - - let node = namehash.hash(name); - - return self.ens.methods.owner(node).call().then((owner) => { - if (owner !== "0x" || owner !== undefined) { - console.warn("name has already been claimed, see owner: ", owner); - return; - } - return self.ens.methods.setSubnodeOwner(node, ); - }).then((addr) => { - - return addr; - }).catch(err => err); -}*/ From 220800fcc3e6bf8099658e71e050fdd7bd77cfce Mon Sep 17 00:00:00 2001 From: VoR0220 Date: Mon, 18 Jun 2018 12:52:02 -0500 Subject: [PATCH 12/17] get rid of global web3 in ens Signed-off-by: VoR0220 --- lib/modules/ens/index.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/modules/ens/index.js b/lib/modules/ens/index.js index f0206b8f7..9cca1345d 100644 --- a/lib/modules/ens/index.js +++ b/lib/modules/ens/index.js @@ -1,4 +1,3 @@ -/*global web3*/ const fs = require('../../core/fs.js'); const utils = require('../../utils/utils.js'); @@ -87,7 +86,7 @@ class ENS { } addSetProvider(config) { - + let code = "\nEmbarkJS.Names.setProvider('ens'," + JSON.stringify(config) + ");"; let shouldInit = (namesConfig) => { From 77001ee8f861f51c69ef8ceefc11b7844105e35b Mon Sep 17 00:00:00 2001 From: VoR0220 Date: Mon, 18 Jun 2018 13:15:54 -0500 Subject: [PATCH 13/17] get rid of unnecessary contracts for this iteration Signed-off-by: VoR0220 --- lib/modules/ens/contracts/DNSResolver.sol | 27 - lib/modules/ens/contracts/Deed.sol | 85 --- .../ens/contracts/DefaultReverseResolver.sol | 47 -- .../ens/contracts/HashRegistrarSimplified.sol | 535 ------------------ lib/modules/ens/contracts/PublicResolver.sol | 238 -------- lib/modules/ens/contracts/TestRegistrar.sol | 37 -- 6 files changed, 969 deletions(-) delete mode 100644 lib/modules/ens/contracts/DNSResolver.sol delete mode 100644 lib/modules/ens/contracts/Deed.sol delete mode 100644 lib/modules/ens/contracts/DefaultReverseResolver.sol delete mode 100644 lib/modules/ens/contracts/HashRegistrarSimplified.sol delete mode 100644 lib/modules/ens/contracts/PublicResolver.sol delete mode 100644 lib/modules/ens/contracts/TestRegistrar.sol diff --git a/lib/modules/ens/contracts/DNSResolver.sol b/lib/modules/ens/contracts/DNSResolver.sol deleted file mode 100644 index 027f45423..000000000 --- a/lib/modules/ens/contracts/DNSResolver.sol +++ /dev/null @@ -1,27 +0,0 @@ -pragma solidity ^0.4.18; - -contract DNSResolver { - address public owner; - mapping (bytes32 => bytes) zones; - - modifier owner_only { - require(msg.sender == owner); - _; - } - - function DNSResolver() public { - owner = msg.sender; - } - - function setDnsrr(bytes32 node, bytes data) public owner_only { - zones[node] = data; - } - - function dnsrr(bytes32 node) public view returns (bytes) { - return zones[node]; - } - - function supportsInterface(bytes4 interfaceID) public pure returns (bool) { - return interfaceID == 0x126a710e; - } -} diff --git a/lib/modules/ens/contracts/Deed.sol b/lib/modules/ens/contracts/Deed.sol deleted file mode 100644 index 4c859d6e7..000000000 --- a/lib/modules/ens/contracts/Deed.sol +++ /dev/null @@ -1,85 +0,0 @@ -pragma solidity ^0.4.18; - -/** - * @title Deed to hold ether in exchange for ownership of a node - * @dev The deed can be controlled only by the registrar and can only send ether back to the owner. - */ -contract Deed { - - address constant burn = 0xdead; - - address public registrar; - address public owner; - address public previousOwner; - - uint public creationDate; - uint public value; - - bool active; - - event OwnerChanged(address newOwner); - event DeedClosed(); - - modifier onlyRegistrar { - require(msg.sender == registrar); - _; - } - - modifier onlyActive { - require(active); - _; - } - - function Deed(address _owner) public payable { - owner = _owner; - registrar = msg.sender; - creationDate = now; - active = true; - value = msg.value; - } - - function setOwner(address newOwner) public onlyRegistrar { - require(newOwner != 0); - previousOwner = owner; // This allows contracts to check who sent them the ownership - owner = newOwner; - OwnerChanged(newOwner); - } - - function setRegistrar(address newRegistrar) public onlyRegistrar { - registrar = newRegistrar; - } - - function setBalance(uint newValue, bool throwOnFailure) public onlyRegistrar onlyActive { - // Check if it has enough balance to set the value - require(value >= newValue); - value = newValue; - // Send the difference to the owner - require(owner.send(this.balance - newValue) || !throwOnFailure); - } - - /** - * @dev Close a deed and refund a specified fraction of the bid value - * - * @param refundRatio The amount*1/1000 to refund - */ - function closeDeed(uint refundRatio) public onlyRegistrar onlyActive { - active = false; - require(burn.send(((1000 - refundRatio) * this.balance)/1000)); - DeedClosed(); - destroyDeed(); - } - - /** - * @dev Close a deed and refund a specified fraction of the bid value - */ - function destroyDeed() public { - require(!active); - - // Instead of selfdestruct(owner), invoke owner fallback function to allow - // owner to log an event if desired; but owner should also be aware that - // its fallback function can also be invoked by setBalance - if (owner.send(this.balance)) { - selfdestruct(burn); - } - } -} diff --git a/lib/modules/ens/contracts/DefaultReverseResolver.sol b/lib/modules/ens/contracts/DefaultReverseResolver.sol deleted file mode 100644 index c9df305be..000000000 --- a/lib/modules/ens/contracts/DefaultReverseResolver.sol +++ /dev/null @@ -1,47 +0,0 @@ -pragma solidity ^0.4.18; - -import "./ReverseRegistrar.sol"; - -/** - * @dev Provides a default implementation of a resolver for reverse records, - * which permits only the owner to update it. - */ -contract DefaultReverseResolver is Resolver { - // namehash('addr.reverse') - bytes32 constant ADDR_REVERSE_NODE = 0x91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e2; - - ENS public ens; - mapping (bytes32 => string) public name; - - /** - * @dev Only permits calls by the reverse registrar. - * @param node The node permission is required for. - */ - modifier owner_only(bytes32 node) { - require(msg.sender == ens.owner(node)); - _; - } - - /** - * @dev Constructor - * @param ensAddr The address of the ENS registry. - */ - function DefaultReverseResolver(ENS ensAddr) public { - ens = ensAddr; - - // Assign ownership of the reverse record to our deployer - ReverseRegistrar registrar = ReverseRegistrar(ens.owner(ADDR_REVERSE_NODE)); - if (address(registrar) != 0) { - registrar.claim(msg.sender); - } - } - - /** - * @dev Sets the name for a node. - * @param node The node to update. - * @param _name The name to set. - */ - function setName(bytes32 node, string _name) public owner_only(node) { - name[node] = _name; - } -} diff --git a/lib/modules/ens/contracts/HashRegistrarSimplified.sol b/lib/modules/ens/contracts/HashRegistrarSimplified.sol deleted file mode 100644 index 35952ae8f..000000000 --- a/lib/modules/ens/contracts/HashRegistrarSimplified.sol +++ /dev/null @@ -1,535 +0,0 @@ -pragma solidity ^0.4.18; - - -/* - -Temporary Hash Registrar -======================== - -This is a simplified version of a hash registrar. It is purporsefully limited: -names cannot be six letters or shorter, new auctions will stop after 4 years. - -The plan is to test the basic features and then move to a new contract in at most -2 years, when some sort of renewal mechanism will be enabled. -*/ - - -import './ENS.sol'; -import './Deed.sol'; - -/** - * @title Registrar - * @dev The registrar handles the auction process for each subnode of the node it owns. - */ -contract Registrar { - ENS public ens; - bytes32 public rootNode; - - mapping (bytes32 => Entry) _entries; - mapping (address => mapping (bytes32 => Deed)) public sealedBids; - - enum Mode { Open, Auction, Owned, Forbidden, Reveal, NotYetAvailable } - - uint32 constant totalAuctionLength = 5 days; - uint32 constant revealPeriod = 48 hours; - uint32 public constant launchLength = 8 weeks; - - uint constant minPrice = 0.01 ether; - uint public registryStarted; - - event AuctionStarted(bytes32 indexed hash, uint registrationDate); - event NewBid(bytes32 indexed hash, address indexed bidder, uint deposit); - event BidRevealed(bytes32 indexed hash, address indexed owner, uint value, uint8 status); - event HashRegistered(bytes32 indexed hash, address indexed owner, uint value, uint registrationDate); - event HashReleased(bytes32 indexed hash, uint value); - event HashInvalidated(bytes32 indexed hash, string indexed name, uint value, uint registrationDate); - - struct Entry { - Deed deed; - uint registrationDate; - uint value; - uint highestBid; - } - - modifier inState(bytes32 _hash, Mode _state) { - require(state(_hash) == _state); - _; - } - - modifier onlyOwner(bytes32 _hash) { - require(state(_hash) == Mode.Owned && msg.sender == _entries[_hash].deed.owner()); - _; - } - - modifier registryOpen() { - require(now >= registryStarted && now <= registryStarted + 4 years && ens.owner(rootNode) == address(this)); - _; - } - - /** - * @dev Constructs a new Registrar, with the provided address as the owner of the root node. - * - * @param _ens The address of the ENS - * @param _rootNode The hash of the rootnode. - */ - function Registrar(ENS _ens, bytes32 _rootNode, uint _startDate) public { - ens = _ens; - rootNode = _rootNode; - registryStarted = _startDate > 0 ? _startDate : now; - } - - /** - * @dev Start an auction for an available hash - * - * @param _hash The hash to start an auction on - */ - function startAuction(bytes32 _hash) public registryOpen() { - Mode mode = state(_hash); - if (mode == Mode.Auction) return; - require(mode == Mode.Open); - - Entry storage newAuction = _entries[_hash]; - newAuction.registrationDate = now + totalAuctionLength; - newAuction.value = 0; - newAuction.highestBid = 0; - AuctionStarted(_hash, newAuction.registrationDate); - } - - /** - * @dev Start multiple auctions for better anonymity - * - * Anyone can start an auction by sending an array of hashes that they want to bid for. - * Arrays are sent so that someone can open up an auction for X dummy hashes when they - * are only really interested in bidding for one. This will increase the cost for an - * attacker to simply bid blindly on all new auctions. Dummy auctions that are - * open but not bid on are closed after a week. - * - * @param _hashes An array of hashes, at least one of which you presumably want to bid on - */ - function startAuctions(bytes32[] _hashes) public { - for (uint i = 0; i < _hashes.length; i ++) { - startAuction(_hashes[i]); - } - } - - /** - * @dev Submit a new sealed bid on a desired hash in a blind auction - * - * Bids are sent by sending a message to the main contract with a hash and an amount. The hash - * contains information about the bid, including the bidded hash, the bid amount, and a random - * salt. Bids are not tied to any one auction until they are revealed. The value of the bid - * itself can be masqueraded by sending more than the value of your actual bid. This is - * followed by a 48h reveal period. Bids revealed after this period will be burned and the ether unrecoverable. - * Since this is an auction, it is expected that most public hashes, like known domains and common dictionary - * words, will have multiple bidders pushing the price up. - * - * @param sealedBid A sealedBid, created by the shaBid function - */ - function newBid(bytes32 sealedBid) public payable { - require(address(sealedBids[msg.sender][sealedBid]) == 0x0); - require(msg.value >= minPrice); - - // Creates a new hash contract with the owner - Deed newBid = (new Deed).value(msg.value)(msg.sender); - sealedBids[msg.sender][sealedBid] = newBid; - NewBid(sealedBid, msg.sender, msg.value); - } - - /** - * @dev Start a set of auctions and bid on one of them - * - * This method functions identically to calling `startAuctions` followed by `newBid`, - * but all in one transaction. - * - * @param hashes A list of hashes to start auctions on. - * @param sealedBid A sealed bid for one of the auctions. - */ - function startAuctionsAndBid(bytes32[] hashes, bytes32 sealedBid) public payable { - startAuctions(hashes); - newBid(sealedBid); - } - - /** - * @dev Submit the properties of a bid to reveal them - * - * @param _hash The node in the sealedBid - * @param _value The bid amount in the sealedBid - * @param _salt The sale in the sealedBid - */ - function unsealBid(bytes32 _hash, uint _value, bytes32 _salt) public { - bytes32 seal = shaBid(_hash, msg.sender, _value, _salt); - Deed bid = sealedBids[msg.sender][seal]; - require(address(bid) != 0); - - sealedBids[msg.sender][seal] = Deed(0); - Entry storage h = _entries[_hash]; - uint value = min(_value, bid.value()); - bid.setBalance(value, true); - - var auctionState = state(_hash); - if (auctionState == Mode.Owned) { - // Too late! Bidder loses their bid. Gets 0.5% back. - bid.closeDeed(5); - BidRevealed(_hash, msg.sender, value, 1); - } else if (auctionState != Mode.Reveal) { - // Invalid phase - revert(); - } else if (value < minPrice || bid.creationDate() > h.registrationDate - revealPeriod) { - // Bid too low or too late, refund 99.5% - bid.closeDeed(995); - BidRevealed(_hash, msg.sender, value, 0); - } else if (value > h.highestBid) { - // New winner - // Cancel the other bid, refund 99.5% - if (address(h.deed) != 0) { - Deed previousWinner = h.deed; - previousWinner.closeDeed(995); - } - - // Set new winner - // Per the rules of a vickery auction, the value becomes the previous highestBid - h.value = h.highestBid; // will be zero if there's only 1 bidder - h.highestBid = value; - h.deed = bid; - BidRevealed(_hash, msg.sender, value, 2); - } else if (value > h.value) { - // Not winner, but affects second place - h.value = value; - bid.closeDeed(995); - BidRevealed(_hash, msg.sender, value, 3); - } else { - // Bid doesn't affect auction - bid.closeDeed(995); - BidRevealed(_hash, msg.sender, value, 4); - } - } - - /** - * @dev Cancel a bid - * - * @param seal The value returned by the shaBid function - */ - function cancelBid(address bidder, bytes32 seal) public { - Deed bid = sealedBids[bidder][seal]; - - // If a sole bidder does not `unsealBid` in time, they have a few more days - // where they can call `startAuction` (again) and then `unsealBid` during - // the revealPeriod to get back their bid value. - // For simplicity, they should call `startAuction` within - // 9 days (2 weeks - totalAuctionLength), otherwise their bid will be - // cancellable by anyone. - require(address(bid) != 0 && now >= bid.creationDate() + totalAuctionLength + 2 weeks); - - // Send the canceller 0.5% of the bid, and burn the rest. - bid.setOwner(msg.sender); - bid.closeDeed(5); - sealedBids[bidder][seal] = Deed(0); - BidRevealed(seal, bidder, 0, 5); - } - - /** - * @dev Finalize an auction after the registration date has passed - * - * @param _hash The hash of the name the auction is for - */ - function finalizeAuction(bytes32 _hash) public onlyOwner(_hash) { - Entry storage h = _entries[_hash]; - - // Handles the case when there's only a single bidder (h.value is zero) - h.value = max(h.value, minPrice); - h.deed.setBalance(h.value, true); - - trySetSubnodeOwner(_hash, h.deed.owner()); - HashRegistered(_hash, h.deed.owner(), h.value, h.registrationDate); - } - - /** - * @dev The owner of a domain may transfer it to someone else at any time. - * - * @param _hash The node to transfer - * @param newOwner The address to transfer ownership to - */ - function transfer(bytes32 _hash, address newOwner) public onlyOwner(_hash) { - require(newOwner != 0); - - Entry storage h = _entries[_hash]; - h.deed.setOwner(newOwner); - trySetSubnodeOwner(_hash, newOwner); - } - - /** - * @dev After some time, or if we're no longer the registrar, the owner can release - * the name and get their ether back. - * - * @param _hash The node to release - */ - function releaseDeed(bytes32 _hash) public onlyOwner(_hash) { - Entry storage h = _entries[_hash]; - Deed deedContract = h.deed; - - require(now >= h.registrationDate + 1 years || ens.owner(rootNode) != address(this)); - - h.value = 0; - h.highestBid = 0; - h.deed = Deed(0); - - _tryEraseSingleNode(_hash); - deedContract.closeDeed(1000); - HashReleased(_hash, h.value); - } - - /** - * @dev Submit a name 6 characters long or less. If it has been registered, - * the submitter will earn 50% of the deed value. - * - * We are purposefully handicapping the simplified registrar as a way - * to force it into being restructured in a few years. - * - * @param unhashedName An invalid name to search for in the registry. - */ - function invalidateName(string unhashedName) public inState(keccak256(unhashedName), Mode.Owned) { - require(strlen(unhashedName) <= 6); - bytes32 hash = keccak256(unhashedName); - - Entry storage h = _entries[hash]; - - _tryEraseSingleNode(hash); - - if (address(h.deed) != 0) { - // Reward the discoverer with 50% of the deed - // The previous owner gets 50% - h.value = max(h.value, minPrice); - h.deed.setBalance(h.value/2, false); - h.deed.setOwner(msg.sender); - h.deed.closeDeed(1000); - } - - HashInvalidated(hash, unhashedName, h.value, h.registrationDate); - - h.value = 0; - h.highestBid = 0; - h.deed = Deed(0); - } - - /** - * @dev Allows anyone to delete the owner and resolver records for a (subdomain of) a - * name that is not currently owned in the registrar. If passing, eg, 'foo.bar.eth', - * the owner and resolver fields on 'foo.bar.eth' and 'bar.eth' will all be cleared. - * - * @param labels A series of label hashes identifying the name to zero out, rooted at the - * registrar's root. Must contain at least one element. For instance, to zero - * 'foo.bar.eth' on a registrar that owns '.eth', pass an array containing - * [keccak256('foo'), keccak256('bar')]. - */ - function eraseNode(bytes32[] labels) public { - require(labels.length != 0); - require(state(labels[labels.length - 1]) != Mode.Owned); - - _eraseNodeHierarchy(labels.length - 1, labels, rootNode); - } - - /** - * @dev Transfers the deed to the current registrar, if different from this one. - * - * Used during the upgrade process to a permanent registrar. - * - * @param _hash The name hash to transfer. - */ - function transferRegistrars(bytes32 _hash) public onlyOwner(_hash) { - address registrar = ens.owner(rootNode); - require(registrar != address(this)); - - // Migrate the deed - Entry storage h = _entries[_hash]; - h.deed.setRegistrar(registrar); - - // Call the new registrar to accept the transfer - Registrar(registrar).acceptRegistrarTransfer(_hash, h.deed, h.registrationDate); - - // Zero out the Entry - h.deed = Deed(0); - h.registrationDate = 0; - h.value = 0; - h.highestBid = 0; - } - - /** - * @dev Accepts a transfer from a previous registrar; stubbed out here since there - * is no previous registrar implementing this interface. - * - * @param hash The sha3 hash of the label to transfer. - * @param deed The Deed object for the name being transferred in. - * @param registrationDate The date at which the name was originally registered. - */ - function acceptRegistrarTransfer(bytes32 hash, Deed deed, uint registrationDate) public { - hash; deed; registrationDate; // Don't warn about unused variables - } - - // State transitions for names: - // Open -> Auction (startAuction) - // Auction -> Reveal - // Reveal -> Owned - // Reveal -> Open (if nobody bid) - // Owned -> Open (releaseDeed or invalidateName) - function state(bytes32 _hash) public view returns (Mode) { - Entry storage entry = _entries[_hash]; - - if (!isAllowed(_hash, now)) { - return Mode.NotYetAvailable; - } else if (now < entry.registrationDate) { - if (now < entry.registrationDate - revealPeriod) { - return Mode.Auction; - } else { - return Mode.Reveal; - } - } else { - if (entry.highestBid == 0) { - return Mode.Open; - } else { - return Mode.Owned; - } - } - } - - function entries(bytes32 _hash) public view returns (Mode, address, uint, uint, uint) { - Entry storage h = _entries[_hash]; - return (state(_hash), h.deed, h.registrationDate, h.value, h.highestBid); - } - - /** - * @dev Determines if a name is available for registration yet - * - * Each name will be assigned a random date in which its auction - * can be started, from 0 to 8 weeks - * - * @param _hash The hash to start an auction on - * @param _timestamp The timestamp to query about - */ - function isAllowed(bytes32 _hash, uint _timestamp) public view returns (bool allowed) { - return _timestamp > getAllowedTime(_hash); - } - - /** - * @dev Returns available date for hash - * - * The available time from the `registryStarted` for a hash is proportional - * to its numeric value. - * - * @param _hash The hash to start an auction on - */ - function getAllowedTime(bytes32 _hash) public view returns (uint) { - return registryStarted + ((launchLength * (uint(_hash) >> 128)) >> 128); - // Right shift operator: a >> b == a / 2**b - } - - /** - * @dev Hash the values required for a secret bid - * - * @param hash The node corresponding to the desired namehash - * @param value The bid amount - * @param salt A random value to ensure secrecy of the bid - * @return The hash of the bid values - */ - function shaBid(bytes32 hash, address owner, uint value, bytes32 salt) public pure returns (bytes32) { - return keccak256(hash, owner, value, salt); - } - - function _tryEraseSingleNode(bytes32 label) internal { - if (ens.owner(rootNode) == address(this)) { - ens.setSubnodeOwner(rootNode, label, address(this)); - bytes32 node = keccak256(rootNode, label); - ens.setResolver(node, 0); - ens.setOwner(node, 0); - } - } - - function _eraseNodeHierarchy(uint idx, bytes32[] labels, bytes32 node) internal { - // Take ownership of the node - ens.setSubnodeOwner(node, labels[idx], address(this)); - node = keccak256(node, labels[idx]); - - // Recurse if there are more labels - if (idx > 0) { - _eraseNodeHierarchy(idx - 1, labels, node); - } - - // Erase the resolver and owner records - ens.setResolver(node, 0); - ens.setOwner(node, 0); - } - - /** - * @dev Assign the owner in ENS, if we're still the registrar - * - * @param _hash hash to change owner - * @param _newOwner new owner to transfer to - */ - function trySetSubnodeOwner(bytes32 _hash, address _newOwner) internal { - if (ens.owner(rootNode) == address(this)) - ens.setSubnodeOwner(rootNode, _hash, _newOwner); - } - - /** - * @dev Returns the maximum of two unsigned integers - * - * @param a A number to compare - * @param b A number to compare - * @return The maximum of two unsigned integers - */ - function max(uint a, uint b) internal pure returns (uint) { - if (a > b) - return a; - else - return b; - } - - /** - * @dev Returns the minimum of two unsigned integers - * - * @param a A number to compare - * @param b A number to compare - * @return The minimum of two unsigned integers - */ - function min(uint a, uint b) internal pure returns (uint) { - if (a < b) - return a; - else - return b; - } - - /** - * @dev Returns the length of a given string - * - * @param s The string to measure the length of - * @return The length of the input string - */ - function strlen(string s) internal pure returns (uint) { - s; // Don't warn about unused variables - // Starting here means the LSB will be the byte we care about - uint ptr; - uint end; - assembly { - ptr := add(s, 1) - end := add(mload(s), ptr) - } - for (uint len = 0; ptr < end; len++) { - uint8 b; - assembly { b := and(mload(ptr), 0xFF) } - if (b < 0x80) { - ptr += 1; - } else if (b < 0xE0) { - ptr += 2; - } else if (b < 0xF0) { - ptr += 3; - } else if (b < 0xF8) { - ptr += 4; - } else if (b < 0xFC) { - ptr += 5; - } else { - ptr += 6; - } - } - return len; - } - -} diff --git a/lib/modules/ens/contracts/PublicResolver.sol b/lib/modules/ens/contracts/PublicResolver.sol deleted file mode 100644 index 1d02357d0..000000000 --- a/lib/modules/ens/contracts/PublicResolver.sol +++ /dev/null @@ -1,238 +0,0 @@ -pragma solidity ^0.4.18; - -import './ENS.sol'; - -/** - * A simple resolver anyone can use; only allows the owner of a node to set its - * address. - */ -contract PublicResolver { - - bytes4 constant INTERFACE_META_ID = 0x01ffc9a7; - bytes4 constant ADDR_INTERFACE_ID = 0x3b3b57de; - bytes4 constant CONTENT_INTERFACE_ID = 0xd8389dc5; - bytes4 constant NAME_INTERFACE_ID = 0x691f3431; - bytes4 constant ABI_INTERFACE_ID = 0x2203ab56; - bytes4 constant PUBKEY_INTERFACE_ID = 0xc8690233; - bytes4 constant TEXT_INTERFACE_ID = 0x59d1d43c; - bytes4 constant MULTIHASH_INTERFACE_ID = 0xe89401a1; - - 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); - event MultihashChanged(bytes32 indexed node, bytes hash); - - struct PublicKey { - bytes32 x; - bytes32 y; - } - - struct Record { - address addr; - bytes32 content; - string name; - PublicKey pubkey; - mapping(string=>string) text; - mapping(uint256=>bytes) abis; - bytes multihash; - } - - ENS ens; - - mapping (bytes32 => Record) records; - - modifier only_owner(bytes32 node) { - require(ens.owner(node) == msg.sender); - _; - } - - /** - * Constructor. - * @param ensAddr The ENS registrar contract. - */ - function PublicResolver(ENS ensAddr) public { - ens = ensAddr; - } - - /** - * 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; - AddrChanged(node, addr); - } - - /** - * 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; - ContentChanged(node, hash); - } - - /** - * Sets the multihash 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 hash The multihash to set - */ - function setMultihash(bytes32 node, bytes hash) public only_owner(node) { - records[node].multihash = hash; - MultihashChanged(node, hash); - } - - /** - * 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; - 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; - 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); - 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; - 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 multihash associated with an ENS node. - * @param node The ENS node to query. - * @return The associated multihash. - */ - function multihash(bytes32 node) public view returns (bytes) { - return records[node].multihash; - } - - /** - * 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; - } - - /** - * Returns true if the resolver implements the interface specified by the provided hash. - * @param interfaceID The ID of the interface to check for. - * @return True if the contract implements the requested interface. - */ - function supportsInterface(bytes4 interfaceID) public pure returns (bool) { - return interfaceID == ADDR_INTERFACE_ID || - interfaceID == CONTENT_INTERFACE_ID || - interfaceID == NAME_INTERFACE_ID || - interfaceID == ABI_INTERFACE_ID || - interfaceID == PUBKEY_INTERFACE_ID || - interfaceID == TEXT_INTERFACE_ID || - interfaceID == MULTIHASH_INTERFACE_ID || - interfaceID == INTERFACE_META_ID; - } -} diff --git a/lib/modules/ens/contracts/TestRegistrar.sol b/lib/modules/ens/contracts/TestRegistrar.sol deleted file mode 100644 index c46421eeb..000000000 --- a/lib/modules/ens/contracts/TestRegistrar.sol +++ /dev/null @@ -1,37 +0,0 @@ -pragma solidity ^0.4.18; - -import './ENS.sol'; - -/** - * A registrar that allocates subdomains to the first person to claim them, but - * expires registrations a fixed period after they're initially claimed. - */ -contract TestRegistrar { - uint constant registrationPeriod = 4 weeks; - - ENS public ens; - bytes32 public rootNode; - mapping (bytes32 => uint) public expiryTimes; - - /** - * Constructor. - * @param ensAddr The address of the ENS registry. - * @param node The node that this registrar administers. - */ - function TestRegistrar(ENS ensAddr, bytes32 node) public { - ens = ensAddr; - rootNode = node; - } - - /** - * Register a name that's not currently registered - * @param subnode The hash of the label to register. - * @param owner The address of the new owner. - */ - function register(bytes32 subnode, address owner) public { - require(expiryTimes[subnode] < now); - - expiryTimes[subnode] = now + registrationPeriod; - ens.setSubnodeOwner(rootNode, subnode, owner); - } -} From 800269d97b3227d4accea7a159b45500023aebe0 Mon Sep 17 00:00:00 2001 From: VoR0220 Date: Mon, 18 Jun 2018 13:54:37 -0500 Subject: [PATCH 14/17] more unnecessary contracts gotten rid of, and fixes made to Embarkjs file Signed-off-by: VoR0220 --- lib/modules/ens/contracts/FIFSRegistrar.sol | 36 ------ .../ens/contracts/ReverseRegistrar.sol | 117 ------------------ lib/modules/ens/embarkjs.js | 15 +-- 3 files changed, 8 insertions(+), 160 deletions(-) delete mode 100644 lib/modules/ens/contracts/FIFSRegistrar.sol delete mode 100644 lib/modules/ens/contracts/ReverseRegistrar.sol diff --git a/lib/modules/ens/contracts/FIFSRegistrar.sol b/lib/modules/ens/contracts/FIFSRegistrar.sol deleted file mode 100644 index 62b7f270b..000000000 --- a/lib/modules/ens/contracts/FIFSRegistrar.sol +++ /dev/null @@ -1,36 +0,0 @@ -pragma solidity ^0.4.18; - -import './ENS.sol'; - -/** - * A registrar that allocates subdomains to the first person to claim them. - */ -contract FIFSRegistrar { - ENS ens; - bytes32 rootNode; - - modifier only_owner(bytes32 subnode) { - address currentOwner = ens.owner(keccak256(rootNode, subnode)); - require(currentOwner == 0 || currentOwner == msg.sender); - _; - } - - /** - * Constructor. - * @param ensAddr The address of the ENS registry. - * @param node The node that this registrar administers. - */ - function FIFSRegistrar(ENS ensAddr, bytes32 node) public { - ens = ensAddr; - rootNode = node; - } - - /** - * Register a name, or change the owner of an existing registration. - * @param subnode The hash of the label to register. - * @param owner The address of the new owner. - */ - function register(bytes32 subnode, address owner) public only_owner(subnode) { - ens.setSubnodeOwner(rootNode, subnode, owner); - } -} diff --git a/lib/modules/ens/contracts/ReverseRegistrar.sol b/lib/modules/ens/contracts/ReverseRegistrar.sol deleted file mode 100644 index d30557292..000000000 --- a/lib/modules/ens/contracts/ReverseRegistrar.sol +++ /dev/null @@ -1,117 +0,0 @@ -pragma solidity ^0.4.10; - -import "./ENS.sol"; - -contract Resolver { - function setName(bytes32 node, string name) public; -} - -contract ReverseRegistrar { - // namehash('addr.reverse') - bytes32 constant ADDR_REVERSE_NODE = 0x91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e2; - - ENS public ens; - Resolver public defaultResolver; - - /** - * @dev Constructor - * @param ensAddr The address of the ENS registry. - * @param resolverAddr The address of the default reverse resolver. - */ - function ReverseRegistrar(ENS ensAddr, Resolver resolverAddr) public { - ens = ensAddr; - defaultResolver = resolverAddr; - - // Assign ownership of the reverse record to our deployer - ReverseRegistrar oldRegistrar = ReverseRegistrar(ens.owner(ADDR_REVERSE_NODE)); - if (address(oldRegistrar) != 0) { - oldRegistrar.claim(msg.sender); - } - } - - /** - * @dev Transfers ownership of the reverse ENS record associated with the - * calling account. - * @param owner The address to set as the owner of the reverse record in ENS. - * @return The ENS node hash of the reverse record. - */ - function claim(address owner) public returns (bytes32) { - return claimWithResolver(owner, 0); - } - - /** - * @dev Transfers ownership of the reverse ENS record associated with the - * calling account. - * @param owner The address to set as the owner of the reverse record in ENS. - * @param resolver The address of the resolver to set; 0 to leave unchanged. - * @return The ENS node hash of the reverse record. - */ - function claimWithResolver(address owner, address resolver) public returns (bytes32) { - var label = sha3HexAddress(msg.sender); - bytes32 node = keccak256(ADDR_REVERSE_NODE, label); - var currentOwner = ens.owner(node); - - // Update the resolver if required - if (resolver != 0 && resolver != ens.resolver(node)) { - // Transfer the name to us first if it's not already - if (currentOwner != address(this)) { - ens.setSubnodeOwner(ADDR_REVERSE_NODE, label, this); - currentOwner = address(this); - } - ens.setResolver(node, resolver); - } - - // Update the owner if required - if (currentOwner != owner) { - ens.setSubnodeOwner(ADDR_REVERSE_NODE, label, owner); - } - - return node; - } - - /** - * @dev Sets the `name()` record for the reverse ENS record associated with - * the calling account. First updates the resolver to the default reverse - * resolver if necessary. - * @param name The name to set for this address. - * @return The ENS node hash of the reverse record. - */ - function setName(string name) public returns (bytes32) { - bytes32 node = claimWithResolver(this, defaultResolver); - defaultResolver.setName(node, name); - return node; - } - - /** - * @dev Returns the node hash for a given account's reverse records. - * @param addr The address to hash - * @return The ENS node hash. - */ - function node(address addr) public view returns (bytes32) { - return keccak256(ADDR_REVERSE_NODE, sha3HexAddress(addr)); - } - - /** - * @dev An optimised function to compute the sha3 of the lower-case - * hexadecimal representation of an Ethereum address. - * @param addr The address to hash - * @return The SHA3 hash of the lower-case hexadecimal encoding of the - * input address. - */ - function sha3HexAddress(address addr) private returns (bytes32 ret) { - addr; ret; // Stop warning us about unused variables - assembly { - let lookup := 0x3031323334353637383961626364656600000000000000000000000000000000 - let i := 40 - loop: - i := sub(i, 1) - mstore8(i, byte(and(addr, 0xf), lookup)) - addr := div(addr, 0x10) - i := sub(i, 1) - mstore8(i, byte(and(addr, 0xf), lookup)) - addr := div(addr, 0x10) - jumpi(loop, i) - ret := keccak256(0, 40) - } - } -} diff --git a/lib/modules/ens/embarkjs.js b/lib/modules/ens/embarkjs.js index 0b549ebde..f3b51e8cd 100644 --- a/lib/modules/ens/embarkjs.js +++ b/lib/modules/ens/embarkjs.js @@ -172,11 +172,13 @@ __embarkENS.resolve = function (name) { }).catch(err => err); }; -__embarkENS.lookup = function (address) { +__embarkENS.lookup = function (address, cb) { const self = this; - if (self.ens === undefined) return; - + if (!self.ens) { + console.log("ENS provider not set. Exitting."); + return; + } if (address.startsWith("0x")) address = address.slice(2); let node = namehash.hash(address.toLowerCase() + ".addr.reverse"); @@ -186,9 +188,8 @@ __embarkENS.lookup = function (address) { return resolverContract.methods.name(node).call(); }).then((name) => { if (name === "" || name === undefined) { - console.warn("ENS name not found"); - return; + cb(new Error("Name not found"), null); } - return name; - }).catch(err => err); + cb(null, name); + }).catch(err => cb(err)); }; From ca5a60b5f0fa33144954131127229dbc5b3b33c2 Mon Sep 17 00:00:00 2001 From: VoR0220 Date: Mon, 18 Jun 2018 14:31:22 -0500 Subject: [PATCH 15/17] callback fixes and get rid of resolver interface Signed-off-by: VoR0220 --- lib/modules/ens/contracts/ResolverInterface.sol | 10 ---------- lib/modules/ens/embarkjs.js | 6 +++--- lib/modules/ens/index.js | 2 +- 3 files changed, 4 insertions(+), 14 deletions(-) delete mode 100644 lib/modules/ens/contracts/ResolverInterface.sol diff --git a/lib/modules/ens/contracts/ResolverInterface.sol b/lib/modules/ens/contracts/ResolverInterface.sol deleted file mode 100644 index 006bf2013..000000000 --- a/lib/modules/ens/contracts/ResolverInterface.sol +++ /dev/null @@ -1,10 +0,0 @@ -pragma solidity ^0.4.18; - -contract ResolverInterface { - function PublicResolver(address ensAddr) public; - function setAddr(bytes32 node, address addr) public; - function setHash(bytes32 node, bytes32 hash) public; - function addr(bytes32 node) public view returns (address); - function hash(bytes32 node) public view returns (bytes32); - function supportsInterface(bytes4 interfaceID) public pure returns (bool); -} diff --git a/lib/modules/ens/embarkjs.js b/lib/modules/ens/embarkjs.js index f3b51e8cd..a41b4c145 100644 --- a/lib/modules/ens/embarkjs.js +++ b/lib/modules/ens/embarkjs.js @@ -188,8 +188,8 @@ __embarkENS.lookup = function (address, cb) { return resolverContract.methods.name(node).call(); }).then((name) => { if (name === "" || name === undefined) { - cb(new Error("Name not found"), null); + return cb(new Error("Name not found")); } - cb(null, name); - }).catch(err => cb(err)); + return cb(null, name); + }).catch(cb); }; diff --git a/lib/modules/ens/index.js b/lib/modules/ens/index.js index 9cca1345d..585c34bb1 100644 --- a/lib/modules/ens/index.js +++ b/lib/modules/ens/index.js @@ -20,7 +20,7 @@ class ENS { address: contract.deployedAddress }; self.addSetProvider(config); - return cb(); + cb(); }); }); } From a9a460f10e11a84f98a2e53b76564287e5f16130 Mon Sep 17 00:00:00 2001 From: VoR0220 Date: Mon, 18 Jun 2018 14:57:43 -0500 Subject: [PATCH 16/17] back to promisification Signed-off-by: VoR0220 --- lib/modules/ens/embarkjs.js | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/lib/modules/ens/embarkjs.js b/lib/modules/ens/embarkjs.js index a41b4c145..7de0ab96e 100644 --- a/lib/modules/ens/embarkjs.js +++ b/lib/modules/ens/embarkjs.js @@ -172,11 +172,11 @@ __embarkENS.resolve = function (name) { }).catch(err => err); }; -__embarkENS.lookup = function (address, cb) { +__embarkENS.lookup = function (address) { const self = this; if (!self.ens) { - console.log("ENS provider not set. Exitting."); + console.log("ENS provider not set. Exiting.") return; } if (address.startsWith("0x")) address = address.slice(2); @@ -186,10 +186,5 @@ __embarkENS.lookup = function (address, cb) { return self.ens.methods.resolver(node).call().then((resolverAddress) => { let resolverContract = new web3.eth.Contract(self.resolverInterface, resolverAddress); return resolverContract.methods.name(node).call(); - }).then((name) => { - if (name === "" || name === undefined) { - return cb(new Error("Name not found")); - } - return cb(null, name); - }).catch(cb); + }).catch(err => err); }; From 7eac4df38d006796a2d4ffe31154b14da2d4cf9c Mon Sep 17 00:00:00 2001 From: VoR0220 Date: Mon, 18 Jun 2018 15:07:42 -0500 Subject: [PATCH 17/17] missing semicolon Signed-off-by: VoR0220 --- lib/modules/ens/embarkjs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/modules/ens/embarkjs.js b/lib/modules/ens/embarkjs.js index 7de0ab96e..09286a1ae 100644 --- a/lib/modules/ens/embarkjs.js +++ b/lib/modules/ens/embarkjs.js @@ -176,7 +176,7 @@ __embarkENS.lookup = function (address) { const self = this; if (!self.ens) { - console.log("ENS provider not set. Exiting.") + console.log("ENS provider not set. Exiting."); return; } if (address.startsWith("0x")) address = address.slice(2);