pragmasolidity >=0.8.4;interfaceARBID{
// Logged when the owner of a node assigns a new owner to a subnode.eventNewOwner(bytes32indexed node, bytes32indexed label, address owner);
// Logged when the owner of a node transfers ownership to a new account.eventTransfer(bytes32indexed node, address owner);
// Logged when the resolver for a node changes.eventNewResolver(bytes32indexed node, address resolver);
// Logged when the TTL of a node changeseventNewTTL(bytes32indexed node, uint64 ttl);
// Logged when an operator is added or removed.eventApprovalForAll(addressindexed owner,
addressindexed operator,
bool approved
);
functionsetRecord(bytes32 node,
address owner,
address resolver,
uint64 ttl
) external;
functionsetSubnodeRecord(bytes32 node,
bytes32 label,
address owner,
address resolver,
uint64 ttl
) external;
functionsetSubnodeOwner(bytes32 node,
bytes32 label,
address owner
) externalreturns (bytes32);
functionsetResolver(bytes32 node, address resolver) external;
functionsetOwner(bytes32 node, address owner) external;
functionsetTTL(bytes32 node, uint64 ttl) external;
functionsetApprovalForAll(address operator, bool approved) external;
functionowner(bytes32 node) externalviewreturns (address);
functionresolver(bytes32 node) externalviewreturns (address);
functionttl(bytes32 node) externalviewreturns (uint64);
functionrecordExists(bytes32 node) externalviewreturns (bool);
functionisApprovedForAll(address owner, address operator)
externalviewreturns (bool);
}
Contract Source Code
File 2 of 6: Context.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)pragmasolidity ^0.8.0;/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/abstractcontractContext{
function_msgSender() internalviewvirtualreturns (address) {
returnmsg.sender;
}
function_msgData() internalviewvirtualreturns (bytescalldata) {
returnmsg.data;
}
}
Contract Source Code
File 3 of 6: Controllable.sol
pragmasolidity ^0.8.4;import"@openzeppelin/contracts/access/Ownable.sol";
contractControllableisOwnable{
mapping(address=>bool) public controllers;
eventControllerChanged(addressindexed controller, bool enabled);
modifieronlyController{
require(
controllers[msg.sender],
"Controllable: Caller is not a controller"
);
_;
}
functionsetController(address controller, bool enabled) publiconlyOwner{
controllers[controller] = enabled;
emit ControllerChanged(controller, enabled);
}
}
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)pragmasolidity ^0.8.0;import"../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/abstractcontractOwnableisContext{
addressprivate _owner;
eventOwnershipTransferred(addressindexed previousOwner, addressindexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Returns the address of the current owner.
*/functionowner() publicviewvirtualreturns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/modifieronlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/functionrenounceOwnership() publicvirtualonlyOwner{
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/functiontransferOwnership(address newOwner) publicvirtualonlyOwner{
require(newOwner !=address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/function_transferOwnership(address newOwner) internalvirtual{
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
Contract Source Code
File 6 of 6: ReverseRegistrar.sol
pragmasolidity >=0.8.4;import"./ARBID.sol";
import"./IReverseRegistrar.sol";
import"@openzeppelin/contracts/access/Ownable.sol";
import"../root/Controllable.sol";
abstractcontractNameResolver{
functionsetName(bytes32 node, stringmemory name) publicvirtual;
}
bytes32constant lookup =0x3031323334353637383961626364656600000000000000000000000000000000;
bytes32constant ADDR_REVERSE_NODE =0x91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e2;
// namehash('addr.reverse')contractReverseRegistrarisOwnable, Controllable, IReverseRegistrar{
ARBID publicimmutable arbid;
NameResolver public defaultResolver;
eventReverseClaimed(addressindexed addr, bytes32indexed node);
/**
* @dev Constructor
* @param arbidAddr The address of the arbid registry.
*/constructor(ARBID arbidAddr) {
arbid = arbidAddr;
// Assign ownership of the reverse record to our deployer
ReverseRegistrar oldRegistrar = ReverseRegistrar(
arbidAddr.owner(ADDR_REVERSE_NODE)
);
if (address(oldRegistrar) !=address(0x0)) {
oldRegistrar.claim(msg.sender);
}
}
modifierauthorised(address addr) {
require(
addr ==msg.sender||
controllers[msg.sender] ||
arbid.isApprovedForAll(addr, msg.sender) ||
ownsContract(addr),
"ReverseRegistrar: Caller is not a controller or authorised by address or the address itself"
);
_;
}
functionsetDefaultResolver(address resolver) publicoverrideonlyOwner{
require(
address(resolver) !=address(0),
"ReverseRegistrar: Resolver address must not be 0"
);
defaultResolver = NameResolver(resolver);
}
/**
* @dev Transfers ownership of the reverse arbid record associated with the
* calling account.
* @param owner The address to set as the owner of the reverse record in arbid.
* @return The arbid node hash of the reverse record.
*/functionclaim(address owner) publicoverridereturns (bytes32) {
return claimForAddr(msg.sender, owner, address(defaultResolver));
}
/**
* @dev Transfers ownership of the reverse arbid record associated with the
* calling account.
* @param addr The reverse record to set
* @param owner The address to set as the owner of the reverse record in arbid.
* @return The arbid node hash of the reverse record.
*/functionclaimForAddr(address addr,
address owner,
address resolver
) publicoverrideauthorised(addr) returns (bytes32) {
bytes32 labelHash = sha3HexAddress(addr);
bytes32 reverseNode =keccak256(
abi.encodePacked(ADDR_REVERSE_NODE, labelHash)
);
emit ReverseClaimed(addr, reverseNode);
arbid.setSubnodeRecord(ADDR_REVERSE_NODE, labelHash, owner, resolver, 0);
return reverseNode;
}
/**
* @dev Transfers ownership of the reverse arbid record associated with the
* calling account.
* @param owner The address to set as the owner of the reverse record in arbid.
* @param resolver The address of the resolver to set; 0 to leave unchanged.
* @return The arbid node hash of the reverse record.
*/functionclaimWithResolver(address owner, address resolver)
publicoverridereturns (bytes32)
{
return claimForAddr(msg.sender, owner, resolver);
}
/**
* @dev Sets the `name()` record for the reverse arbid 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 arbid node hash of the reverse record.
*/functionsetName(stringmemory name) publicoverridereturns (bytes32) {
return
setNameForAddr(
msg.sender,
msg.sender,
address(defaultResolver),
name
);
}
/**
* @dev Sets the `name()` record for the reverse arbid record associated with
* the account provided. First updates the resolver to the default reverse
* resolver if necessary.
* Only callable by controllers and authorised users
* @param addr The reverse record to set
* @param owner The owner of the reverse node
* @param name The name to set for this address.
* @return The arbid node hash of the reverse record.
*/functionsetNameForAddr(address addr,
address owner,
address resolver,
stringmemory name
) publicoverridereturns (bytes32) {
bytes32 node = claimForAddr(addr, owner, resolver);
NameResolver(resolver).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 arbid node hash.
*/functionnode(address addr) publicpureoverridereturns (bytes32) {
returnkeccak256(
abi.encodePacked(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 ret The SHA3 hash of the lower-case hexadecimal encoding of the
* input address.
*/functionsha3HexAddress(address addr) privatepurereturns (bytes32 ret) {
assembly {
for {
let i :=40
} gt(i, 0) {
} {
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)
}
ret :=keccak256(0, 40)
}
}
functionownsContract(address addr) internalviewreturns (bool) {
try Ownable(addr).owner() returns (address owner) {
return owner ==msg.sender;
} catch {
returnfalse;
}
}
}