编译器
0.8.17+commit.8df45f5f
文件 1 的 23:Address.sol
pragma solidity ^0.8.1;
library Address {
function isContract(address account) internal view returns (bool) {
return account.code.length > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
文件 2 的 23:BytesUtils.sol
pragma solidity ~0.8.17;
library BytesUtils {
function keccak(
bytes memory self,
uint256 offset,
uint256 len
) internal pure returns (bytes32 ret) {
require(offset + len <= self.length);
assembly {
ret := keccak256(add(add(self, 32), offset), len)
}
}
function namehash(
bytes memory self,
uint256 offset
) internal pure returns (bytes32) {
(bytes32 labelhash, uint256 newOffset) = readLabel(self, offset);
if (labelhash == bytes32(0)) {
require(offset == self.length - 1, "namehash: Junk at end of name");
return bytes32(0);
}
return
keccak256(abi.encodePacked(namehash(self, newOffset), labelhash));
}
function readLabel(
bytes memory self,
uint256 idx
) internal pure returns (bytes32 labelhash, uint256 newIdx) {
require(idx < self.length, "readLabel: Index out of bounds");
uint256 len = uint256(uint8(self[idx]));
if (len > 0) {
labelhash = keccak(self, idx + 1, len);
} else {
labelhash = bytes32(0);
}
newIdx = idx + len + 1;
}
}
文件 3 的 23:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 4 的 23:Controllable.sol
pragma solidity ~0.8.17;
import "@openzeppelin/contracts/access/Ownable.sol";
contract Controllable is Ownable {
mapping(address => bool) public controllers;
event ControllerChanged(address indexed controller, bool active);
function setController(address controller, bool active) public onlyOwner {
controllers[controller] = active;
emit ControllerChanged(controller, active);
}
modifier onlyController() {
require(
controllers[msg.sender],
"Controllable: Caller is not a controller"
);
_;
}
}
文件 5 的 23:ENS.sol
pragma solidity >=0.8.4;
interface ENS {
event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);
event Transfer(bytes32 indexed node, address owner);
event NewResolver(bytes32 indexed node, address resolver);
event NewTTL(bytes32 indexed node, uint64 ttl);
event ApprovalForAll(
address indexed owner,
address indexed operator,
bool approved
);
function setRecord(
bytes32 node,
address owner,
address resolver,
uint64 ttl
) external;
function setSubnodeRecord(
bytes32 node,
bytes32 label,
address owner,
address resolver,
uint64 ttl
) external;
function setSubnodeOwner(
bytes32 node,
bytes32 label,
address owner
) external returns (bytes32);
function setResolver(bytes32 node, address resolver) external;
function setOwner(bytes32 node, address owner) external;
function setTTL(bytes32 node, uint64 ttl) external;
function setApprovalForAll(address operator, bool approved) external;
function owner(bytes32 node) external view returns (address);
function resolver(bytes32 node) external view returns (address);
function ttl(bytes32 node) external view returns (uint64);
function recordExists(bytes32 node) external view returns (bool);
function isApprovedForAll(
address owner,
address operator
) external view returns (bool);
}
文件 6 的 23:ERC1155Fuse.sol
pragma solidity ~0.8.17;
import "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol";
import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
import "@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol";
import "@openzeppelin/contracts/utils/Address.sol";
abstract contract ERC1155Fuse is ERC165, IERC1155, IERC1155MetadataURI {
using Address for address;
event Approval(
address indexed owner,
address indexed approved,
uint256 indexed tokenId
);
mapping(uint256 => uint256) public _tokens;
mapping(address => mapping(address => bool)) private _operatorApprovals;
mapping(uint256 => address) internal _tokenApprovals;
function ownerOf(uint256 id) public view virtual returns (address) {
(address owner, , ) = getData(id);
return owner;
}
function approve(address to, uint256 tokenId) public virtual {
address owner = ownerOf(tokenId);
require(to != owner, "ERC721: approval to current owner");
require(
msg.sender == owner || isApprovedForAll(owner, msg.sender),
"ERC721: approve caller is not token owner or approved for all"
);
_approve(to, tokenId);
}
function getApproved(
uint256 tokenId
) public view virtual returns (address) {
return _tokenApprovals[tokenId];
}
function supportsInterface(
bytes4 interfaceId
) public view virtual override(ERC165, IERC165) returns (bool) {
return
interfaceId == type(IERC1155).interfaceId ||
interfaceId == type(IERC1155MetadataURI).interfaceId ||
super.supportsInterface(interfaceId);
}
function balanceOf(
address account,
uint256 id
) public view virtual override returns (uint256) {
require(
account != address(0),
"ERC1155: balance query for the zero address"
);
address owner = ownerOf(id);
if (owner == account) {
return 1;
}
return 0;
}
function balanceOfBatch(
address[] memory accounts,
uint256[] memory ids
) public view virtual override returns (uint256[] memory) {
require(
accounts.length == ids.length,
"ERC1155: accounts and ids length mismatch"
);
uint256[] memory batchBalances = new uint256[](accounts.length);
for (uint256 i = 0; i < accounts.length; ++i) {
batchBalances[i] = balanceOf(accounts[i], ids[i]);
}
return batchBalances;
}
function setApprovalForAll(
address operator,
bool approved
) public virtual override {
require(
msg.sender != operator,
"ERC1155: setting approval status for self"
);
_operatorApprovals[msg.sender][operator] = approved;
emit ApprovalForAll(msg.sender, operator, approved);
}
function isApprovedForAll(
address account,
address operator
) public view virtual override returns (bool) {
return _operatorApprovals[account][operator];
}
function getData(
uint256 tokenId
) public view virtual returns (address owner, uint32 fuses, uint64 expiry) {
uint256 t = _tokens[tokenId];
owner = address(uint160(t));
expiry = uint64(t >> 192);
fuses = uint32(t >> 160);
}
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes memory data
) public virtual override {
require(to != address(0), "ERC1155: transfer to the zero address");
require(
from == msg.sender || isApprovedForAll(from, msg.sender),
"ERC1155: caller is not owner nor approved"
);
_transfer(from, to, id, amount, data);
}
function safeBatchTransferFrom(
address from,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) public virtual override {
require(
ids.length == amounts.length,
"ERC1155: ids and amounts length mismatch"
);
require(to != address(0), "ERC1155: transfer to the zero address");
require(
from == msg.sender || isApprovedForAll(from, msg.sender),
"ERC1155: transfer caller is not owner nor approved"
);
for (uint256 i = 0; i < ids.length; ++i) {
uint256 id = ids[i];
uint256 amount = amounts[i];
(address oldOwner, uint32 fuses, uint64 expiry) = getData(id);
_beforeTransfer(id, fuses, expiry);
require(
amount == 1 && oldOwner == from,
"ERC1155: insufficient balance for transfer"
);
_setData(id, to, fuses, expiry);
}
emit TransferBatch(msg.sender, from, to, ids, amounts);
_doSafeBatchTransferAcceptanceCheck(
msg.sender,
from,
to,
ids,
amounts,
data
);
}
function _setData(
uint256 tokenId,
address owner,
uint32 fuses,
uint64 expiry
) internal virtual {
_tokens[tokenId] =
uint256(uint160(owner)) |
(uint256(fuses) << 160) |
(uint256(expiry) << 192);
}
function _beforeTransfer(
uint256 id,
uint32 fuses,
uint64 expiry
) internal virtual;
function _clearOwnerAndFuses(
address owner,
uint32 fuses,
uint64 expiry
) internal virtual returns (address, uint32);
function _mint(
bytes32 node,
address owner,
uint32 fuses,
uint64 expiry
) internal virtual {
uint256 tokenId = uint256(node);
(address oldOwner, uint32 oldFuses, uint64 oldExpiry) = getData(
uint256(node)
);
uint32 parentControlledFuses = (uint32(type(uint16).max) << 16) &
oldFuses;
if (oldExpiry > expiry) {
expiry = oldExpiry;
}
if (oldExpiry >= block.timestamp) {
fuses = fuses | parentControlledFuses;
}
require(oldOwner == address(0), "ERC1155: mint of existing token");
require(owner != address(0), "ERC1155: mint to the zero address");
require(
owner != address(this),
"ERC1155: newOwner cannot be the NameWrapper contract"
);
_setData(tokenId, owner, fuses, expiry);
emit TransferSingle(msg.sender, address(0x0), owner, tokenId, 1);
_doSafeTransferAcceptanceCheck(
msg.sender,
address(0),
owner,
tokenId,
1,
""
);
}
function _burn(uint256 tokenId) internal virtual {
(address oldOwner, uint32 fuses, uint64 expiry) = ERC1155Fuse.getData(
tokenId
);
(, fuses) = _clearOwnerAndFuses(oldOwner, fuses, expiry);
delete _tokenApprovals[tokenId];
_setData(tokenId, address(0x0), fuses, expiry);
emit TransferSingle(msg.sender, oldOwner, address(0x0), tokenId, 1);
}
function _transfer(
address from,
address to,
uint256 id,
uint256 amount,
bytes memory data
) internal {
(address oldOwner, uint32 fuses, uint64 expiry) = getData(id);
_beforeTransfer(id, fuses, expiry);
require(
amount == 1 && oldOwner == from,
"ERC1155: insufficient balance for transfer"
);
if (oldOwner == to) {
return;
}
_setData(id, to, fuses, expiry);
emit TransferSingle(msg.sender, from, to, id, amount);
_doSafeTransferAcceptanceCheck(msg.sender, from, to, id, amount, data);
}
function _doSafeTransferAcceptanceCheck(
address operator,
address from,
address to,
uint256 id,
uint256 amount,
bytes memory data
) private {
if (to.isContract()) {
try
IERC1155Receiver(to).onERC1155Received(
operator,
from,
id,
amount,
data
)
returns (bytes4 response) {
if (
response != IERC1155Receiver(to).onERC1155Received.selector
) {
revert("ERC1155: ERC1155Receiver rejected tokens");
}
} catch Error(string memory reason) {
revert(reason);
} catch {
revert("ERC1155: transfer to non ERC1155Receiver implementer");
}
}
}
function _doSafeBatchTransferAcceptanceCheck(
address operator,
address from,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) private {
if (to.isContract()) {
try
IERC1155Receiver(to).onERC1155BatchReceived(
operator,
from,
ids,
amounts,
data
)
returns (bytes4 response) {
if (
response !=
IERC1155Receiver(to).onERC1155BatchReceived.selector
) {
revert("ERC1155: ERC1155Receiver rejected tokens");
}
} catch Error(string memory reason) {
revert(reason);
} catch {
revert("ERC1155: transfer to non ERC1155Receiver implementer");
}
}
}
function _approve(address to, uint256 tokenId) internal virtual {
_tokenApprovals[tokenId] = to;
emit Approval(ownerOf(tokenId), to, tokenId);
}
}
文件 7 的 23:ERC165.sol
pragma solidity ^0.8.0;
import "./IERC165.sol";
abstract contract ERC165 is IERC165 {
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
文件 8 的 23:ERC20Recoverable.sol
pragma solidity >=0.8.17 <0.9.0;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
contract ERC20Recoverable is Ownable {
function recoverFunds(
address _token,
address _to,
uint256 _amount
) external onlyOwner {
IERC20(_token).transfer(_to, _amount);
}
}
文件 9 的 23:IBaseRegistrar.sol
import "../registry/ENS.sol";
import "./IBaseRegistrar.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
interface IBaseRegistrar is IERC721 {
event ControllerAdded(address indexed controller);
event ControllerRemoved(address indexed controller);
event NameMigrated(
uint256 indexed id,
address indexed owner,
uint256 expires
);
event NameRegistered(
uint256 indexed id,
address indexed owner,
uint256 expires
);
event NameRenewed(uint256 indexed id, uint256 expires);
function addController(address controller) external;
function removeController(address controller) external;
function setResolver(address resolver) external;
function nameExpires(uint256 id) external view returns (uint256);
function available(uint256 id) external view returns (bool);
function register(
uint256 id,
address owner,
uint256 duration
) external returns (uint256);
function renew(uint256 id, uint256 duration) external returns (uint256);
function reclaim(uint256 id, address owner) external;
}
文件 10 的 23:IERC1155.sol
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
interface IERC1155 is IERC165 {
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
event TransferBatch(
address indexed operator,
address indexed from,
address indexed to,
uint256[] ids,
uint256[] values
);
event ApprovalForAll(address indexed account, address indexed operator, bool approved);
event URI(string value, uint256 indexed id);
function balanceOf(address account, uint256 id) external view returns (uint256);
function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)
external
view
returns (uint256[] memory);
function setApprovalForAll(address operator, bool approved) external;
function isApprovedForAll(address account, address operator) external view returns (bool);
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes calldata data
) external;
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata amounts,
bytes calldata data
) external;
}
文件 11 的 23:IERC1155MetadataURI.sol
pragma solidity ^0.8.0;
import "../IERC1155.sol";
interface IERC1155MetadataURI is IERC1155 {
function uri(uint256 id) external view returns (string memory);
}
文件 12 的 23:IERC1155Receiver.sol
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
interface IERC1155Receiver is IERC165 {
function onERC1155Received(
address operator,
address from,
uint256 id,
uint256 value,
bytes calldata data
) external returns (bytes4);
function onERC1155BatchReceived(
address operator,
address from,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external returns (bytes4);
}
文件 13 的 23:IERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 14 的 23:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
}
文件 15 的 23:IERC721.sol
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
interface IERC721 is IERC165 {
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
function balanceOf(address owner) external view returns (uint256 balance);
function ownerOf(uint256 tokenId) external view returns (address owner);
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
function approve(address to, uint256 tokenId) external;
function setApprovalForAll(address operator, bool _approved) external;
function getApproved(uint256 tokenId) external view returns (address operator);
function isApprovedForAll(address owner, address operator) external view returns (bool);
}
文件 16 的 23:IERC721Receiver.sol
pragma solidity ^0.8.0;
interface IERC721Receiver {
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}
文件 17 的 23:IMetadataService.sol
pragma solidity ~0.8.17;
interface IMetadataService {
function uri(uint256) external view returns (string memory);
}
文件 18 的 23:INameWrapper.sol
pragma solidity ~0.8.17;
import "../registry/ENS.sol";
import "../ethregistrar/IBaseRegistrar.sol";
import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
import "./IMetadataService.sol";
import "./INameWrapperUpgrade.sol";
uint32 constant CANNOT_UNWRAP = 1;
uint32 constant CANNOT_BURN_FUSES = 2;
uint32 constant CANNOT_TRANSFER = 4;
uint32 constant CANNOT_SET_RESOLVER = 8;
uint32 constant CANNOT_SET_TTL = 16;
uint32 constant CANNOT_CREATE_SUBDOMAIN = 32;
uint32 constant CANNOT_APPROVE = 64;
uint32 constant PARENT_CANNOT_CONTROL = 1 << 16;
uint32 constant IS_DOT_ETH = 1 << 17;
uint32 constant CAN_EXTEND_EXPIRY = 1 << 18;
uint32 constant CAN_DO_EVERYTHING = 0;
uint32 constant PARENT_CONTROLLED_FUSES = 0xFFFF0000;
uint32 constant USER_SETTABLE_FUSES = 0xFFFDFFFF;
interface INameWrapper is IERC1155 {
event NameWrapped(
bytes32 indexed node,
bytes name,
address owner,
uint32 fuses,
uint64 expiry
);
event NameUnwrapped(bytes32 indexed node, address owner);
event FusesSet(bytes32 indexed node, uint32 fuses);
event ExpiryExtended(bytes32 indexed node, uint64 expiry);
function ens() external view returns (ENS);
function registrar() external view returns (IBaseRegistrar);
function metadataService() external view returns (IMetadataService);
function names(bytes32) external view returns (bytes memory);
function name() external view returns (string memory);
function upgradeContract() external view returns (INameWrapperUpgrade);
function supportsInterface(bytes4 interfaceID) external view returns (bool);
function wrap(
bytes calldata name,
address wrappedOwner,
address resolver
) external;
function wrapETH2LD(
string calldata label,
address wrappedOwner,
uint16 ownerControlledFuses,
address resolver
) external returns (uint64 expires);
function registerAndWrapETH2LD(
string calldata label,
address wrappedOwner,
uint256 duration,
address resolver,
uint16 ownerControlledFuses
) external returns (uint256 registrarExpiry);
function renew(
uint256 labelHash,
uint256 duration
) external returns (uint256 expires);
function unwrap(bytes32 node, bytes32 label, address owner) external;
function unwrapETH2LD(
bytes32 label,
address newRegistrant,
address newController
) external;
function upgrade(bytes calldata name, bytes calldata extraData) external;
function setFuses(
bytes32 node,
uint16 ownerControlledFuses
) external returns (uint32 newFuses);
function setChildFuses(
bytes32 parentNode,
bytes32 labelhash,
uint32 fuses,
uint64 expiry
) external;
function setSubnodeRecord(
bytes32 node,
string calldata label,
address owner,
address resolver,
uint64 ttl,
uint32 fuses,
uint64 expiry
) external returns (bytes32);
function setRecord(
bytes32 node,
address owner,
address resolver,
uint64 ttl
) external;
function setSubnodeOwner(
bytes32 node,
string calldata label,
address newOwner,
uint32 fuses,
uint64 expiry
) external returns (bytes32);
function extendExpiry(
bytes32 node,
bytes32 labelhash,
uint64 expiry
) external returns (uint64);
function canModifyName(
bytes32 node,
address addr
) external view returns (bool);
function setResolver(bytes32 node, address resolver) external;
function setTTL(bytes32 node, uint64 ttl) external;
function ownerOf(uint256 id) external view returns (address owner);
function approve(address to, uint256 tokenId) external;
function getApproved(uint256 tokenId) external view returns (address);
function getData(
uint256 id
) external view returns (address, uint32, uint64);
function setMetadataService(IMetadataService _metadataService) external;
function uri(uint256 tokenId) external view returns (string memory);
function setUpgradeContract(INameWrapperUpgrade _upgradeAddress) external;
function allFusesBurned(
bytes32 node,
uint32 fuseMask
) external view returns (bool);
function isWrapped(bytes32) external view returns (bool);
function isWrapped(bytes32, bytes32) external view returns (bool);
}
文件 19 的 23:INameWrapperUpgrade.sol
pragma solidity ~0.8.17;
interface INameWrapperUpgrade {
function wrapFromUpgrade(
bytes calldata name,
address wrappedOwner,
uint32 fuses,
uint64 expiry,
address approved,
bytes calldata extraData
) external;
}
文件 20 的 23:IReverseRegistrar.sol
pragma solidity >=0.8.4;
interface IReverseRegistrar {
function setDefaultResolver(address resolver) external;
function claim(address owner) external returns (bytes32);
function claimForAddr(
address addr,
address owner,
address resolver
) external returns (bytes32);
function claimWithResolver(
address owner,
address resolver
) external returns (bytes32);
function setName(string memory name) external returns (bytes32);
function setNameForAddr(
address addr,
address owner,
address resolver,
string memory name
) external returns (bytes32);
function node(address addr) external pure returns (bytes32);
}
文件 21 的 23:NameWrapper.sol
pragma solidity ~0.8.17;
import {ERC1155Fuse, IERC165, IERC1155MetadataURI} from "./ERC1155Fuse.sol";
import {Controllable} from "./Controllable.sol";
import {INameWrapper, CANNOT_UNWRAP, CANNOT_BURN_FUSES, CANNOT_TRANSFER, CANNOT_SET_RESOLVER, CANNOT_SET_TTL, CANNOT_CREATE_SUBDOMAIN, CANNOT_APPROVE, PARENT_CANNOT_CONTROL, CAN_DO_EVERYTHING, IS_DOT_ETH, CAN_EXTEND_EXPIRY, PARENT_CONTROLLED_FUSES, USER_SETTABLE_FUSES} from "./INameWrapper.sol";
import {INameWrapperUpgrade} from "./INameWrapperUpgrade.sol";
import {IMetadataService} from "./IMetadataService.sol";
import {ENS} from "../registry/ENS.sol";
import {IReverseRegistrar} from "../reverseRegistrar/IReverseRegistrar.sol";
import {ReverseClaimer} from "../reverseRegistrar/ReverseClaimer.sol";
import {IBaseRegistrar} from "../ethregistrar/IBaseRegistrar.sol";
import {IERC721Receiver} from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {BytesUtils} from "./BytesUtils.sol";
import {ERC20Recoverable} from "../utils/ERC20Recoverable.sol";
error Unauthorised(bytes32 node, address addr);
error IncompatibleParent();
error IncorrectTokenType();
error LabelMismatch(bytes32 labelHash, bytes32 expectedLabelhash);
error LabelTooShort();
error LabelTooLong(string label);
error IncorrectTargetOwner(address owner);
error CannotUpgrade();
error OperationProhibited(bytes32 node);
error NameIsNotWrapped();
error NameIsStillExpired();
contract NameWrapper is
Ownable,
ERC1155Fuse,
INameWrapper,
Controllable,
IERC721Receiver,
ERC20Recoverable,
ReverseClaimer
{
using BytesUtils for bytes;
ENS public immutable ens;
IBaseRegistrar public immutable registrar;
IMetadataService public metadataService;
mapping(bytes32 => bytes) public names;
string public constant name = "NameWrapper";
uint64 private constant GRACE_PERIOD = 90 days;
bytes32 private constant ETH_NODE =
0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae;
bytes32 private constant ETH_LABELHASH =
0x4f5b812789fc606be1b3b16908db13fc7a9adf7ca72641f84d75b47069d3d7f0;
bytes32 private constant ROOT_NODE =
0x0000000000000000000000000000000000000000000000000000000000000000;
INameWrapperUpgrade public upgradeContract;
uint64 private constant MAX_EXPIRY = type(uint64).max;
constructor(
ENS _ens,
IBaseRegistrar _registrar,
IMetadataService _metadataService
) ReverseClaimer(_ens, msg.sender) {
ens = _ens;
registrar = _registrar;
metadataService = _metadataService;
_setData(
uint256(ETH_NODE),
address(0),
uint32(PARENT_CANNOT_CONTROL | CANNOT_UNWRAP),
MAX_EXPIRY
);
_setData(
uint256(ROOT_NODE),
address(0),
uint32(PARENT_CANNOT_CONTROL | CANNOT_UNWRAP),
MAX_EXPIRY
);
names[ROOT_NODE] = "\x00";
names[ETH_NODE] = "\x03eth\x00";
}
function supportsInterface(
bytes4 interfaceId
) public view virtual override(ERC1155Fuse, INameWrapper) returns (bool) {
return
interfaceId == type(INameWrapper).interfaceId ||
interfaceId == type(IERC721Receiver).interfaceId ||
super.supportsInterface(interfaceId);
}
function ownerOf(
uint256 id
) public view override(ERC1155Fuse, INameWrapper) returns (address owner) {
return super.ownerOf(id);
}
function getApproved(
uint256 id
)
public
view
override(ERC1155Fuse, INameWrapper)
returns (address operator)
{
address owner = ownerOf(id);
if (owner == address(0)) {
return address(0);
}
return super.getApproved(id);
}
function approve(
address to,
uint256 tokenId
) public override(ERC1155Fuse, INameWrapper) {
(, uint32 fuses, ) = getData(tokenId);
if (fuses & CANNOT_APPROVE == CANNOT_APPROVE) {
revert OperationProhibited(bytes32(tokenId));
}
super.approve(to, tokenId);
}
function getData(
uint256 id
)
public
view
override(ERC1155Fuse, INameWrapper)
returns (address owner, uint32 fuses, uint64 expiry)
{
(owner, fuses, expiry) = super.getData(id);
(owner, fuses) = _clearOwnerAndFuses(owner, fuses, expiry);
}
function setMetadataService(
IMetadataService _metadataService
) public onlyOwner {
metadataService = _metadataService;
}
function uri(
uint256 tokenId
)
public
view
override(INameWrapper, IERC1155MetadataURI)
returns (string memory)
{
return metadataService.uri(tokenId);
}
function setUpgradeContract(
INameWrapperUpgrade _upgradeAddress
) public onlyOwner {
if (address(upgradeContract) != address(0)) {
registrar.setApprovalForAll(address(upgradeContract), false);
ens.setApprovalForAll(address(upgradeContract), false);
}
upgradeContract = _upgradeAddress;
if (address(upgradeContract) != address(0)) {
registrar.setApprovalForAll(address(upgradeContract), true);
ens.setApprovalForAll(address(upgradeContract), true);
}
}
modifier onlyTokenOwner(bytes32 node) {
if (!canModifyName(node, msg.sender)) {
revert Unauthorised(node, msg.sender);
}
_;
}
function canModifyName(
bytes32 node,
address addr
) public view returns (bool) {
(address owner, uint32 fuses, uint64 expiry) = getData(uint256(node));
return
(owner == addr || isApprovedForAll(owner, addr)) &&
!_isETH2LDInGracePeriod(fuses, expiry);
}
function canExtendSubnames(
bytes32 node,
address addr
) public view returns (bool) {
(address owner, uint32 fuses, uint64 expiry) = getData(uint256(node));
return
(owner == addr ||
isApprovedForAll(owner, addr) ||
getApproved(uint256(node)) == addr) &&
!_isETH2LDInGracePeriod(fuses, expiry);
}
function wrapETH2LD(
string calldata label,
address wrappedOwner,
uint16 ownerControlledFuses,
address resolver
) public returns (uint64 expiry) {
uint256 tokenId = uint256(keccak256(bytes(label)));
address registrant = registrar.ownerOf(tokenId);
if (
registrant != msg.sender &&
!registrar.isApprovedForAll(registrant, msg.sender)
) {
revert Unauthorised(
_makeNode(ETH_NODE, bytes32(tokenId)),
msg.sender
);
}
registrar.transferFrom(registrant, address(this), tokenId);
registrar.reclaim(tokenId, address(this));
expiry = uint64(registrar.nameExpires(tokenId)) + GRACE_PERIOD;
_wrapETH2LD(
label,
wrappedOwner,
ownerControlledFuses,
expiry,
resolver
);
}
function registerAndWrapETH2LD(
string calldata label,
address wrappedOwner,
uint256 duration,
address resolver,
uint16 ownerControlledFuses
) external onlyController returns (uint256 registrarExpiry) {
uint256 tokenId = uint256(keccak256(bytes(label)));
registrarExpiry = registrar.register(tokenId, address(this), duration);
_wrapETH2LD(
label,
wrappedOwner,
ownerControlledFuses,
uint64(registrarExpiry) + GRACE_PERIOD,
resolver
);
}
function renew(
uint256 tokenId,
uint256 duration
) external onlyController returns (uint256 expires) {
bytes32 node = _makeNode(ETH_NODE, bytes32(tokenId));
uint256 registrarExpiry = registrar.renew(tokenId, duration);
try registrar.ownerOf(tokenId) returns (address registrarOwner) {
if (
registrarOwner != address(this) ||
ens.owner(node) != address(this)
) {
return registrarExpiry;
}
} catch {
return registrarExpiry;
}
uint64 expiry = uint64(registrarExpiry) + GRACE_PERIOD;
(address owner, uint32 fuses, ) = super.getData(uint256(node));
_setData(node, owner, fuses, expiry);
return registrarExpiry;
}
function wrap(
bytes calldata name,
address wrappedOwner,
address resolver
) public {
(bytes32 labelhash, uint256 offset) = name.readLabel(0);
bytes32 parentNode = name.namehash(offset);
bytes32 node = _makeNode(parentNode, labelhash);
names[node] = name;
if (parentNode == ETH_NODE) {
revert IncompatibleParent();
}
address owner = ens.owner(node);
if (owner != msg.sender && !ens.isApprovedForAll(owner, msg.sender)) {
revert Unauthorised(node, msg.sender);
}
if (resolver != address(0)) {
ens.setResolver(node, resolver);
}
ens.setOwner(node, address(this));
_wrap(node, name, wrappedOwner, 0, 0);
}
function unwrapETH2LD(
bytes32 labelhash,
address registrant,
address controller
) public onlyTokenOwner(_makeNode(ETH_NODE, labelhash)) {
if (registrant == address(this)) {
revert IncorrectTargetOwner(registrant);
}
_unwrap(_makeNode(ETH_NODE, labelhash), controller);
registrar.safeTransferFrom(
address(this),
registrant,
uint256(labelhash)
);
}
function unwrap(
bytes32 parentNode,
bytes32 labelhash,
address controller
) public onlyTokenOwner(_makeNode(parentNode, labelhash)) {
if (parentNode == ETH_NODE) {
revert IncompatibleParent();
}
if (controller == address(0x0) || controller == address(this)) {
revert IncorrectTargetOwner(controller);
}
_unwrap(_makeNode(parentNode, labelhash), controller);
}
function setFuses(
bytes32 node,
uint16 ownerControlledFuses
)
public
onlyTokenOwner(node)
operationAllowed(node, CANNOT_BURN_FUSES)
returns (uint32)
{
(address owner, uint32 oldFuses, uint64 expiry) = getData(
uint256(node)
);
_setFuses(node, owner, ownerControlledFuses | oldFuses, expiry, expiry);
return oldFuses;
}
function extendExpiry(
bytes32 parentNode,
bytes32 labelhash,
uint64 expiry
) public returns (uint64) {
bytes32 node = _makeNode(parentNode, labelhash);
if (!_isWrapped(node)) {
revert NameIsNotWrapped();
}
bool canExtendSubname = canExtendSubnames(parentNode, msg.sender);
if (!canExtendSubname && !canModifyName(node, msg.sender)) {
revert Unauthorised(node, msg.sender);
}
(address owner, uint32 fuses, uint64 oldExpiry) = getData(
uint256(node)
);
if (!canExtendSubname && fuses & CAN_EXTEND_EXPIRY == 0) {
revert OperationProhibited(node);
}
(, , uint64 maxExpiry) = getData(uint256(parentNode));
expiry = _normaliseExpiry(expiry, oldExpiry, maxExpiry);
_setData(node, owner, fuses, expiry);
emit ExpiryExtended(node, expiry);
return expiry;
}
function upgrade(bytes calldata name, bytes calldata extraData) public {
bytes32 node = name.namehash(0);
if (address(upgradeContract) == address(0)) {
revert CannotUpgrade();
}
if (!canModifyName(node, msg.sender)) {
revert Unauthorised(node, msg.sender);
}
(address currentOwner, uint32 fuses, uint64 expiry) = getData(
uint256(node)
);
address approved = getApproved(uint256(node));
_burn(uint256(node));
upgradeContract.wrapFromUpgrade(
name,
currentOwner,
fuses,
expiry,
approved,
extraData
);
}
function setChildFuses(
bytes32 parentNode,
bytes32 labelhash,
uint32 fuses,
uint64 expiry
) public {
bytes32 node = _makeNode(parentNode, labelhash);
_checkFusesAreSettable(node, fuses);
(address owner, uint32 oldFuses, uint64 oldExpiry) = getData(
uint256(node)
);
if (owner == address(0) || ens.owner(node) != address(this)) {
revert NameIsNotWrapped();
}
(, uint32 parentFuses, uint64 maxExpiry) = getData(uint256(parentNode));
if (parentNode == ROOT_NODE) {
if (!canModifyName(node, msg.sender)) {
revert Unauthorised(node, msg.sender);
}
} else {
if (!canModifyName(parentNode, msg.sender)) {
revert Unauthorised(parentNode, msg.sender);
}
}
_checkParentFuses(node, fuses, parentFuses);
expiry = _normaliseExpiry(expiry, oldExpiry, maxExpiry);
if (
oldFuses & PARENT_CANNOT_CONTROL != 0 &&
oldFuses | fuses != oldFuses
) {
revert OperationProhibited(node);
}
fuses |= oldFuses;
_setFuses(node, owner, fuses, oldExpiry, expiry);
}
function setSubnodeOwner(
bytes32 parentNode,
string calldata label,
address owner,
uint32 fuses,
uint64 expiry
) public onlyTokenOwner(parentNode) returns (bytes32 node) {
bytes32 labelhash = keccak256(bytes(label));
node = _makeNode(parentNode, labelhash);
_checkCanCallSetSubnodeOwner(parentNode, node);
_checkFusesAreSettable(node, fuses);
bytes memory name = _saveLabel(parentNode, node, label);
expiry = _checkParentFusesAndExpiry(parentNode, node, fuses, expiry);
if (!_isWrapped(node)) {
ens.setSubnodeOwner(parentNode, labelhash, address(this));
_wrap(node, name, owner, fuses, expiry);
} else {
_updateName(parentNode, node, label, owner, fuses, expiry);
}
}
function setSubnodeRecord(
bytes32 parentNode,
string memory label,
address owner,
address resolver,
uint64 ttl,
uint32 fuses,
uint64 expiry
) public onlyTokenOwner(parentNode) returns (bytes32 node) {
bytes32 labelhash = keccak256(bytes(label));
node = _makeNode(parentNode, labelhash);
_checkCanCallSetSubnodeOwner(parentNode, node);
_checkFusesAreSettable(node, fuses);
_saveLabel(parentNode, node, label);
expiry = _checkParentFusesAndExpiry(parentNode, node, fuses, expiry);
if (!_isWrapped(node)) {
ens.setSubnodeRecord(
parentNode,
labelhash,
address(this),
resolver,
ttl
);
_storeNameAndWrap(parentNode, node, label, owner, fuses, expiry);
} else {
ens.setSubnodeRecord(
parentNode,
labelhash,
address(this),
resolver,
ttl
);
_updateName(parentNode, node, label, owner, fuses, expiry);
}
}
function setRecord(
bytes32 node,
address owner,
address resolver,
uint64 ttl
)
public
onlyTokenOwner(node)
operationAllowed(
node,
CANNOT_TRANSFER | CANNOT_SET_RESOLVER | CANNOT_SET_TTL
)
{
ens.setRecord(node, address(this), resolver, ttl);
if (owner == address(0)) {
(, uint32 fuses, ) = getData(uint256(node));
if (fuses & IS_DOT_ETH == IS_DOT_ETH) {
revert IncorrectTargetOwner(owner);
}
_unwrap(node, address(0));
} else {
address oldOwner = ownerOf(uint256(node));
_transfer(oldOwner, owner, uint256(node), 1, "");
}
}
function setResolver(
bytes32 node,
address resolver
) public onlyTokenOwner(node) operationAllowed(node, CANNOT_SET_RESOLVER) {
ens.setResolver(node, resolver);
}
function setTTL(
bytes32 node,
uint64 ttl
) public onlyTokenOwner(node) operationAllowed(node, CANNOT_SET_TTL) {
ens.setTTL(node, ttl);
}
modifier operationAllowed(bytes32 node, uint32 fuseMask) {
(, uint32 fuses, ) = getData(uint256(node));
if (fuses & fuseMask != 0) {
revert OperationProhibited(node);
}
_;
}
function _checkCanCallSetSubnodeOwner(
bytes32 parentNode,
bytes32 subnode
) internal view {
(
address subnodeOwner,
uint32 subnodeFuses,
uint64 subnodeExpiry
) = getData(uint256(subnode));
bool expired = subnodeExpiry < block.timestamp;
if (
expired &&
(subnodeOwner == address(0) ||
ens.owner(subnode) == address(0))
) {
(, uint32 parentFuses, ) = getData(uint256(parentNode));
if (parentFuses & CANNOT_CREATE_SUBDOMAIN != 0) {
revert OperationProhibited(subnode);
}
} else {
if (subnodeFuses & PARENT_CANNOT_CONTROL != 0) {
revert OperationProhibited(subnode);
}
}
}
function allFusesBurned(
bytes32 node,
uint32 fuseMask
) public view returns (bool) {
(, uint32 fuses, ) = getData(uint256(node));
return fuses & fuseMask == fuseMask;
}
function isWrapped(bytes32 node) public view returns (bool) {
bytes memory name = names[node];
if (name.length == 0) {
return false;
}
(bytes32 labelhash, uint256 offset) = name.readLabel(0);
bytes32 parentNode = name.namehash(offset);
return isWrapped(parentNode, labelhash);
}
function isWrapped(
bytes32 parentNode,
bytes32 labelhash
) public view returns (bool) {
bytes32 node = _makeNode(parentNode, labelhash);
bool wrapped = _isWrapped(node);
if (parentNode != ETH_NODE) {
return wrapped;
}
try registrar.ownerOf(uint256(labelhash)) returns (address owner) {
return owner == address(this);
} catch {
return false;
}
}
function onERC721Received(
address to,
address,
uint256 tokenId,
bytes calldata data
) public returns (bytes4) {
if (msg.sender != address(registrar)) {
revert IncorrectTokenType();
}
(
string memory label,
address owner,
uint16 ownerControlledFuses,
address resolver
) = abi.decode(data, (string, address, uint16, address));
bytes32 labelhash = bytes32(tokenId);
bytes32 labelhashFromData = keccak256(bytes(label));
if (labelhashFromData != labelhash) {
revert LabelMismatch(labelhashFromData, labelhash);
}
registrar.reclaim(uint256(labelhash), address(this));
uint64 expiry = uint64(registrar.nameExpires(tokenId)) + GRACE_PERIOD;
_wrapETH2LD(label, owner, ownerControlledFuses, expiry, resolver);
return IERC721Receiver(to).onERC721Received.selector;
}
function _beforeTransfer(
uint256 id,
uint32 fuses,
uint64 expiry
) internal override {
if (fuses & IS_DOT_ETH == IS_DOT_ETH) {
expiry -= GRACE_PERIOD;
}
if (expiry < block.timestamp) {
if (fuses & PARENT_CANNOT_CONTROL != 0) {
revert("ERC1155: insufficient balance for transfer");
}
} else {
if (fuses & CANNOT_TRANSFER != 0) {
revert OperationProhibited(bytes32(id));
}
}
if (fuses & CANNOT_APPROVE == 0) {
delete _tokenApprovals[id];
}
}
function _clearOwnerAndFuses(
address owner,
uint32 fuses,
uint64 expiry
) internal view override returns (address, uint32) {
if (expiry < block.timestamp) {
if (fuses & PARENT_CANNOT_CONTROL == PARENT_CANNOT_CONTROL) {
owner = address(0);
}
fuses = 0;
}
return (owner, fuses);
}
function _makeNode(
bytes32 node,
bytes32 labelhash
) private pure returns (bytes32) {
return keccak256(abi.encodePacked(node, labelhash));
}
function _addLabel(
string memory label,
bytes memory name
) internal pure returns (bytes memory ret) {
if (bytes(label).length < 1) {
revert LabelTooShort();
}
if (bytes(label).length > 255) {
revert LabelTooLong(label);
}
return abi.encodePacked(uint8(bytes(label).length), label, name);
}
function _mint(
bytes32 node,
address owner,
uint32 fuses,
uint64 expiry
) internal override {
_canFusesBeBurned(node, fuses);
(address oldOwner, , ) = super.getData(uint256(node));
if (oldOwner != address(0)) {
_burn(uint256(node));
emit NameUnwrapped(node, address(0));
}
super._mint(node, owner, fuses, expiry);
}
function _wrap(
bytes32 node,
bytes memory name,
address wrappedOwner,
uint32 fuses,
uint64 expiry
) internal {
_mint(node, wrappedOwner, fuses, expiry);
emit NameWrapped(node, name, wrappedOwner, fuses, expiry);
}
function _storeNameAndWrap(
bytes32 parentNode,
bytes32 node,
string memory label,
address owner,
uint32 fuses,
uint64 expiry
) internal {
bytes memory name = _addLabel(label, names[parentNode]);
_wrap(node, name, owner, fuses, expiry);
}
function _saveLabel(
bytes32 parentNode,
bytes32 node,
string memory label
) internal returns (bytes memory) {
bytes memory name = _addLabel(label, names[parentNode]);
names[node] = name;
return name;
}
function _updateName(
bytes32 parentNode,
bytes32 node,
string memory label,
address owner,
uint32 fuses,
uint64 expiry
) internal {
(address oldOwner, uint32 oldFuses, uint64 oldExpiry) = getData(
uint256(node)
);
bytes memory name = _addLabel(label, names[parentNode]);
if (names[node].length == 0) {
names[node] = name;
}
_setFuses(node, oldOwner, oldFuses | fuses, oldExpiry, expiry);
if (owner == address(0)) {
_unwrap(node, address(0));
} else {
_transfer(oldOwner, owner, uint256(node), 1, "");
}
}
function _checkParentFusesAndExpiry(
bytes32 parentNode,
bytes32 node,
uint32 fuses,
uint64 expiry
) internal view returns (uint64) {
(, , uint64 oldExpiry) = getData(uint256(node));
(, uint32 parentFuses, uint64 maxExpiry) = getData(uint256(parentNode));
_checkParentFuses(node, fuses, parentFuses);
return _normaliseExpiry(expiry, oldExpiry, maxExpiry);
}
function _checkParentFuses(
bytes32 node,
uint32 fuses,
uint32 parentFuses
) internal pure {
bool isBurningParentControlledFuses = fuses & PARENT_CONTROLLED_FUSES !=
0;
bool parentHasNotBurnedCU = parentFuses & CANNOT_UNWRAP == 0;
if (isBurningParentControlledFuses && parentHasNotBurnedCU) {
revert OperationProhibited(node);
}
}
function _normaliseExpiry(
uint64 expiry,
uint64 oldExpiry,
uint64 maxExpiry
) private pure returns (uint64) {
if (expiry > maxExpiry) {
expiry = maxExpiry;
}
if (expiry < oldExpiry) {
expiry = oldExpiry;
}
return expiry;
}
function _wrapETH2LD(
string memory label,
address wrappedOwner,
uint32 fuses,
uint64 expiry,
address resolver
) private {
bytes32 labelhash = keccak256(bytes(label));
bytes32 node = _makeNode(ETH_NODE, labelhash);
bytes memory name = _addLabel(label, "\x03eth\x00");
names[node] = name;
_wrap(
node,
name,
wrappedOwner,
fuses | PARENT_CANNOT_CONTROL | IS_DOT_ETH,
expiry
);
if (resolver != address(0)) {
ens.setResolver(node, resolver);
}
}
function _unwrap(bytes32 node, address owner) private {
if (allFusesBurned(node, CANNOT_UNWRAP)) {
revert OperationProhibited(node);
}
_burn(uint256(node));
ens.setOwner(node, owner);
emit NameUnwrapped(node, owner);
}
function _setFuses(
bytes32 node,
address owner,
uint32 fuses,
uint64 oldExpiry,
uint64 expiry
) internal {
_setData(node, owner, fuses, expiry);
emit FusesSet(node, fuses);
if (expiry > oldExpiry) {
emit ExpiryExtended(node, expiry);
}
}
function _setData(
bytes32 node,
address owner,
uint32 fuses,
uint64 expiry
) internal {
_canFusesBeBurned(node, fuses);
super._setData(uint256(node), owner, fuses, expiry);
}
function _canFusesBeBurned(bytes32 node, uint32 fuses) internal pure {
if (
fuses & ~PARENT_CONTROLLED_FUSES != 0 &&
fuses & (PARENT_CANNOT_CONTROL | CANNOT_UNWRAP) !=
(PARENT_CANNOT_CONTROL | CANNOT_UNWRAP)
) {
revert OperationProhibited(node);
}
}
function _checkFusesAreSettable(bytes32 node, uint32 fuses) internal pure {
if (fuses | USER_SETTABLE_FUSES != USER_SETTABLE_FUSES) {
revert OperationProhibited(node);
}
}
function _isWrapped(bytes32 node) internal view returns (bool) {
return
ownerOf(uint256(node)) != address(0) &&
ens.owner(node) == address(this);
}
function _isETH2LDInGracePeriod(
uint32 fuses,
uint64 expiry
) internal view returns (bool) {
return
fuses & IS_DOT_ETH == IS_DOT_ETH &&
expiry - GRACE_PERIOD < block.timestamp;
}
}
文件 22 的 23:Ownable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
_transferOwnership(_msgSender());
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 23 的 23:ReverseClaimer.sol
pragma solidity >=0.8.17 <0.9.0;
import {ENS} from "../registry/ENS.sol";
import {IReverseRegistrar} from "../reverseRegistrar/IReverseRegistrar.sol";
contract ReverseClaimer {
bytes32 constant ADDR_REVERSE_NODE =
0x91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e2;
constructor(ENS ens, address claimant) {
IReverseRegistrar reverseRegistrar = IReverseRegistrar(
ens.owner(ADDR_REVERSE_NODE)
);
reverseRegistrar.claim(claimant);
}
}
{
"compilationTarget": {
"contracts/wrapper/NameWrapper.sol": "NameWrapper"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 1300
},
"remappings": []
}
[{"inputs":[{"internalType":"contract ENS","name":"_ens","type":"address"},{"internalType":"contract IBaseRegistrar","name":"_registrar","type":"address"},{"internalType":"contract IMetadataService","name":"_metadataService","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CannotUpgrade","type":"error"},{"inputs":[],"name":"IncompatibleParent","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"IncorrectTargetOwner","type":"error"},{"inputs":[],"name":"IncorrectTokenType","type":"error"},{"inputs":[{"internalType":"bytes32","name":"labelHash","type":"bytes32"},{"internalType":"bytes32","name":"expectedLabelhash","type":"bytes32"}],"name":"LabelMismatch","type":"error"},{"inputs":[{"internalType":"string","name":"label","type":"string"}],"name":"LabelTooLong","type":"error"},{"inputs":[],"name":"LabelTooShort","type":"error"},{"inputs":[],"name":"NameIsNotWrapped","type":"error"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"OperationProhibited","type":"error"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"address","name":"addr","type":"address"}],"name":"Unauthorised","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"controller","type":"address"},{"indexed":false,"internalType":"bool","name":"active","type":"bool"}],"name":"ControllerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"expiry","type":"uint64"}],"name":"ExpiryExtended","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"fuses","type":"uint32"}],"name":"FusesSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"address","name":"owner","type":"address"}],"name":"NameUnwrapped","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"name","type":"bytes"},{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint32","name":"fuses","type":"uint32"},{"indexed":false,"internalType":"uint64","name":"expiry","type":"uint64"}],"name":"NameWrapped","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"_tokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint32","name":"fuseMask","type":"uint32"}],"name":"allFusesBurned","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"address","name":"addr","type":"address"}],"name":"canExtendSubnames","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"address","name":"addr","type":"address"}],"name":"canModifyName","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"controllers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ens","outputs":[{"internalType":"contract ENS","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"parentNode","type":"bytes32"},{"internalType":"bytes32","name":"labelhash","type":"bytes32"},{"internalType":"uint64","name":"expiry","type":"uint64"}],"name":"extendExpiry","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"operator","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getData","outputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint32","name":"fuses","type":"uint32"},{"internalType":"uint64","name":"expiry","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"parentNode","type":"bytes32"},{"internalType":"bytes32","name":"labelhash","type":"bytes32"}],"name":"isWrapped","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"isWrapped","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"metadataService","outputs":[{"internalType":"contract IMetadataService","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"names","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"recoverFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"label","type":"string"},{"internalType":"address","name":"wrappedOwner","type":"address"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"address","name":"resolver","type":"address"},{"internalType":"uint16","name":"ownerControlledFuses","type":"uint16"}],"name":"registerAndWrapETH2LD","outputs":[{"internalType":"uint256","name":"registrarExpiry","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"registrar","outputs":[{"internalType":"contract IBaseRegistrar","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"}],"name":"renew","outputs":[{"internalType":"uint256","name":"expires","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"parentNode","type":"bytes32"},{"internalType":"bytes32","name":"labelhash","type":"bytes32"},{"internalType":"uint32","name":"fuses","type":"uint32"},{"internalType":"uint64","name":"expiry","type":"uint64"}],"name":"setChildFuses","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"controller","type":"address"},{"internalType":"bool","name":"active","type":"bool"}],"name":"setController","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint16","name":"ownerControlledFuses","type":"uint16"}],"name":"setFuses","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IMetadataService","name":"_metadataService","type":"address"}],"name":"setMetadataService","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"resolver","type":"address"},{"internalType":"uint64","name":"ttl","type":"uint64"}],"name":"setRecord","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"address","name":"resolver","type":"address"}],"name":"setResolver","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"parentNode","type":"bytes32"},{"internalType":"string","name":"label","type":"string"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint32","name":"fuses","type":"uint32"},{"internalType":"uint64","name":"expiry","type":"uint64"}],"name":"setSubnodeOwner","outputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"parentNode","type":"bytes32"},{"internalType":"string","name":"label","type":"string"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"resolver","type":"address"},{"internalType":"uint64","name":"ttl","type":"uint64"},{"internalType":"uint32","name":"fuses","type":"uint32"},{"internalType":"uint64","name":"expiry","type":"uint64"}],"name":"setSubnodeRecord","outputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint64","name":"ttl","type":"uint64"}],"name":"setTTL","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract INameWrapperUpgrade","name":"_upgradeAddress","type":"address"}],"name":"setUpgradeContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"parentNode","type":"bytes32"},{"internalType":"bytes32","name":"labelhash","type":"bytes32"},{"internalType":"address","name":"controller","type":"address"}],"name":"unwrap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"labelhash","type":"bytes32"},{"internalType":"address","name":"registrant","type":"address"},{"internalType":"address","name":"controller","type":"address"}],"name":"unwrapETH2LD","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"name","type":"bytes"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"upgrade","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"upgradeContract","outputs":[{"internalType":"contract INameWrapperUpgrade","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"name","type":"bytes"},{"internalType":"address","name":"wrappedOwner","type":"address"},{"internalType":"address","name":"resolver","type":"address"}],"name":"wrap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"label","type":"string"},{"internalType":"address","name":"wrappedOwner","type":"address"},{"internalType":"uint16","name":"ownerControlledFuses","type":"uint16"},{"internalType":"address","name":"resolver","type":"address"}],"name":"wrapETH2LD","outputs":[{"internalType":"uint64","name":"expiry","type":"uint64"}],"stateMutability":"nonpayable","type":"function"}]