文件 1 的 43:Access.sol
pragma solidity >=0.8.4;
import "../universal/UniversalRegistrar.sol";
import "./IExtensionAccess.sol";
abstract contract Access {
UniversalRegistrar public registrar;
constructor(UniversalRegistrar _registrar) {
registrar = _registrar;
}
modifier nodeOperator(bytes32 node) {
require(_isNodeOperator(node, msg.sender), "Caller is not a node operator");
_;
}
modifier nodeApprovedOrOwner(bytes32 node) {
require(_isNodeApprovedOrOwner(node, msg.sender), "Caller is not a node owner nor approved by owner");
_;
}
function isNodeOperator(bytes32 node, address operator) public view returns (bool) {
return _isNodeOperator(node, operator);
}
function isNodeApprovedOrOwner(bytes32 node, address operator) public view returns (bool) {
return _isNodeApprovedOrOwner(node, operator);
}
function _isNodeOperator(bytes32 node, address addr) internal view returns (bool) {
address owner = registrar.ownerOfNode(node);
if (!Address.isContract(owner)) {
return owner == addr;
}
try IERC165(owner).supportsInterface(type(IExtensionAccess).interfaceId) returns (bool supported) {
if (supported) {
return IExtensionAccess(owner).isApprovedOrOwner(addr, uint256(node)) ||
IExtensionAccess(owner).getOperator(uint256(node)) == addr;
}
} catch {}
return owner == addr;
}
function _isNodeApprovedOrOwner(bytes32 node, address addr) internal view returns (bool) {
address owner = registrar.ownerOfNode(node);
if (!Address.isContract(owner)) {
return owner == addr;
}
try IERC165(owner).supportsInterface(type(IExtensionAccess).interfaceId) returns (bool supported) {
if (supported) {
return IExtensionAccess(owner).isApprovedOrOwner(addr, uint256(node));
}
} catch {}
return owner == addr;
}
}
文件 2 的 43: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 functionCall(target, data, "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");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(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) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(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) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
文件 3 的 43:BaseUniversalRegistrarControllerV2.sol
pragma solidity >=0.8.4;
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import "../universal/UniversalRegistrar.sol";
import "./IExtensionPayee.sol";
abstract contract BaseUniversalRegistrarControllerV2 {
event PaymentReleased(bytes32 node, address to, uint256 amount);
uint256 private _totalShares;
uint256 private _registryShare;
uint256 private _ownerShare;
mapping(bytes32 => uint256) private _balances;
mapping(bytes32 => uint256) private _totalReleased;
mapping(bytes32 => uint256) private _registryReleased;
mapping(bytes32 => uint256) private _ownerReleased;
UniversalRegistrar public base;
function ownerPayee(bytes32 node) public view returns (address) {
address owner = base.ownerOfNode(node);
if (Address.isContract(owner)) {
try IERC165(owner).supportsInterface(type(IExtensionPayee).interfaceId) returns (bool supported) {
if (supported) {
return IExtensionPayee(owner).payeeOf(node);
}
} catch {}
}
return owner;
}
function registryPayee() public view returns (address) {
return base.root().owner();
}
constructor(UniversalRegistrar base_, uint256 ownerShare_, uint256 registryShare_) {
base = base_;
_ownerShare = ownerShare_;
_registryShare = registryShare_;
_totalShares = ownerShare_ + registryShare_;
}
function totalShares() external view returns (uint256) {
return _totalShares;
}
function totalReleased(bytes32 node) external view returns (uint256) {
return _totalReleased[node];
}
function ownerShare() external view returns (uint256) {
return _ownerShare;
}
function registryShare() external view returns (uint256) {
return _registryShare;
}
function ownerReleased(bytes32 node) external view returns (uint256) {
return _ownerReleased[node];
}
function registryReleased(bytes32 node) external view returns (uint256) {
return _registryReleased[node];
}
function balance(bytes32 node) external view returns (uint256) {
return _balances[node];
}
function ownerBalance(bytes32 node) public view returns (uint256) {
uint256 totalReceived = _balances[node] + _totalReleased[node];
return _pendingPayment(_ownerShare, totalReceived, _ownerReleased[node]);
}
function registryBalance(bytes32 node) public view returns (uint256) {
uint256 totalReceived = _balances[node] + _totalReleased[node];
return _pendingPayment(_registryShare, totalReceived, _registryReleased[node]);
}
function _addPayment(bytes32 node, uint256 amount) internal {
_balances[node] += amount;
}
function releaseToOwner(bytes32 node) external {
uint256 payment = ownerBalance(node);
require(payment != 0, "owner is not due payment");
_ownerReleased[node] += payment;
_totalReleased[node] += payment;
_balances[node] -= payment;
address owner = ownerPayee(node);
Address.sendValue(payable(owner), payment);
emit PaymentReleased(node, owner, payment);
}
function releaseToRegistry(bytes32 node) external {
uint256 payment = registryBalance(node);
require(payment != 0, "registry is not due payment");
_registryReleased[node] += payment;
_totalReleased[node] += payment;
_balances[node] -= payment;
address rootOwner = registryPayee();
Address.sendValue(payable(rootOwner), payment);
emit PaymentReleased(node, rootOwner, payment);
}
function _pendingPayment(
uint256 shares,
uint256 totalReceived,
uint256 alreadyReleased
) private view returns (uint256) {
return (totalReceived * shares) / _totalShares - alreadyReleased;
}
}
文件 4 的 43: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;
}
}
文件 5 的 43:Controllable.sol
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/access/Ownable.sol";
contract Controllable is Ownable {
mapping(address => bool) public controllers;
event ControllerChanged(address indexed controller, bool enabled);
modifier onlyController {
require(
controllers[msg.sender],
"Controllable: Caller is not a controller"
);
_;
}
function setController(address controller, bool enabled) public onlyOwner {
controllers[controller] = enabled;
emit ControllerChanged(controller, enabled);
}
}
文件 6 的 43: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 virtual;
function setSubnodeRecord(bytes32 node, bytes32 label, address owner, address resolver, uint64 ttl) external virtual;
function setSubnodeOwner(bytes32 node, bytes32 label, address owner) external virtual returns(bytes32);
function setResolver(bytes32 node, address resolver) external virtual;
function setOwner(bytes32 node, address owner) external virtual;
function setTTL(bytes32 node, uint64 ttl) external virtual;
function setApprovalForAll(address operator, bool approved) external virtual;
function owner(bytes32 node) external virtual view returns (address);
function resolver(bytes32 node) external virtual view returns (address);
function ttl(bytes32 node) external virtual view returns (uint64);
function recordExists(bytes32 node) external virtual view returns (bool);
function isApprovedForAll(address owner, address operator) external virtual view returns (bool);
}
文件 7 的 43:ENSRegistry.sol
pragma solidity >=0.8.4;
import "./ENS.sol";
contract ENSRegistry is ENS {
struct Record {
address owner;
address resolver;
uint64 ttl;
}
mapping (bytes32 => Record) records;
mapping (address => mapping(address => bool)) operators;
modifier authorised(bytes32 node) {
address owner = records[node].owner;
require(owner == msg.sender || operators[owner][msg.sender]);
_;
}
constructor() public {
records[0x0].owner = msg.sender;
}
function setRecord(bytes32 node, address owner, address resolver, uint64 ttl) external virtual override {
setOwner(node, owner);
_setResolverAndTTL(node, resolver, ttl);
}
function setSubnodeRecord(bytes32 node, bytes32 label, address owner, address resolver, uint64 ttl) external virtual override {
bytes32 subnode = setSubnodeOwner(node, label, owner);
_setResolverAndTTL(subnode, resolver, ttl);
}
function setOwner(bytes32 node, address owner) public virtual override authorised(node) {
_setOwner(node, owner);
emit Transfer(node, owner);
}
function setSubnodeOwner(bytes32 node, bytes32 label, address owner) public virtual override authorised(node) returns(bytes32) {
bytes32 subnode = keccak256(abi.encodePacked(node, label));
_setOwner(subnode, owner);
emit NewOwner(node, label, owner);
return subnode;
}
function setResolver(bytes32 node, address resolver) public virtual override authorised(node) {
emit NewResolver(node, resolver);
records[node].resolver = resolver;
}
function setTTL(bytes32 node, uint64 ttl) public virtual override authorised(node) {
emit NewTTL(node, ttl);
records[node].ttl = ttl;
}
function setApprovalForAll(address operator, bool approved) external virtual override {
operators[msg.sender][operator] = approved;
emit ApprovalForAll(msg.sender, operator, approved);
}
function owner(bytes32 node) public virtual override view returns (address) {
address addr = records[node].owner;
if (addr == address(this)) {
return address(0x0);
}
return addr;
}
function resolver(bytes32 node) public virtual override view returns (address) {
return records[node].resolver;
}
function ttl(bytes32 node) public virtual override view returns (uint64) {
return records[node].ttl;
}
function recordExists(bytes32 node) public virtual override view returns (bool) {
return records[node].owner != address(0x0);
}
function isApprovedForAll(address owner, address operator) external virtual override view returns (bool) {
return operators[owner][operator];
}
function _setOwner(bytes32 node, address owner) internal virtual {
records[node].owner = owner;
}
function _setResolverAndTTL(bytes32 node, address resolver, uint64 ttl) internal {
if(resolver != records[node].resolver) {
records[node].resolver = resolver;
emit NewResolver(node, resolver);
}
if(ttl != records[node].ttl) {
records[node].ttl = ttl;
emit NewTTL(node, ttl);
}
}
}
文件 8 的 43: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;
}
}
文件 9 的 43:ERC721.sol
pragma solidity ^0.8.0;
import "./IERC721.sol";
import "./IERC721Receiver.sol";
import "./extensions/IERC721Metadata.sol";
import "../../utils/Address.sol";
import "../../utils/Context.sol";
import "../../utils/Strings.sol";
import "../../utils/introspection/ERC165.sol";
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
using Address for address;
using Strings for uint256;
string private _name;
string private _symbol;
mapping(uint256 => address) private _owners;
mapping(address => uint256) private _balances;
mapping(uint256 => address) private _tokenApprovals;
mapping(address => mapping(address => bool)) private _operatorApprovals;
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return
interfaceId == type(IERC721).interfaceId ||
interfaceId == type(IERC721Metadata).interfaceId ||
super.supportsInterface(interfaceId);
}
function balanceOf(address owner) public view virtual override returns (uint256) {
require(owner != address(0), "ERC721: balance query for the zero address");
return _balances[owner];
}
function ownerOf(uint256 tokenId) public view virtual override returns (address) {
address owner = _owners[tokenId];
require(owner != address(0), "ERC721: owner query for nonexistent token");
return owner;
}
function name() public view virtual override returns (string memory) {
return _name;
}
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
string memory baseURI = _baseURI();
return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
}
function _baseURI() internal view virtual returns (string memory) {
return "";
}
function approve(address to, uint256 tokenId) public virtual override {
address owner = ERC721.ownerOf(tokenId);
require(to != owner, "ERC721: approval to current owner");
require(
_msgSender() == owner || isApprovedForAll(owner, _msgSender()),
"ERC721: approve caller is not owner nor approved for all"
);
_approve(to, tokenId);
}
function getApproved(uint256 tokenId) public view virtual override returns (address) {
require(_exists(tokenId), "ERC721: approved query for nonexistent token");
return _tokenApprovals[tokenId];
}
function setApprovalForAll(address operator, bool approved) public virtual override {
_setApprovalForAll(_msgSender(), operator, approved);
}
function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
return _operatorApprovals[owner][operator];
}
function transferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_transfer(from, to, tokenId);
}
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
safeTransferFrom(from, to, tokenId, "");
}
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes memory _data
) public virtual override {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_safeTransfer(from, to, tokenId, _data);
}
function _safeTransfer(
address from,
address to,
uint256 tokenId,
bytes memory _data
) internal virtual {
_transfer(from, to, tokenId);
require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
}
function _exists(uint256 tokenId) internal view virtual returns (bool) {
return _owners[tokenId] != address(0);
}
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
require(_exists(tokenId), "ERC721: operator query for nonexistent token");
address owner = ERC721.ownerOf(tokenId);
return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);
}
function _safeMint(address to, uint256 tokenId) internal virtual {
_safeMint(to, tokenId, "");
}
function _safeMint(
address to,
uint256 tokenId,
bytes memory _data
) internal virtual {
_mint(to, tokenId);
require(
_checkOnERC721Received(address(0), to, tokenId, _data),
"ERC721: transfer to non ERC721Receiver implementer"
);
}
function _mint(address to, uint256 tokenId) internal virtual {
require(to != address(0), "ERC721: mint to the zero address");
require(!_exists(tokenId), "ERC721: token already minted");
_beforeTokenTransfer(address(0), to, tokenId);
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(address(0), to, tokenId);
_afterTokenTransfer(address(0), to, tokenId);
}
function _burn(uint256 tokenId) internal virtual {
address owner = ERC721.ownerOf(tokenId);
_beforeTokenTransfer(owner, address(0), tokenId);
_approve(address(0), tokenId);
_balances[owner] -= 1;
delete _owners[tokenId];
emit Transfer(owner, address(0), tokenId);
_afterTokenTransfer(owner, address(0), tokenId);
}
function _transfer(
address from,
address to,
uint256 tokenId
) internal virtual {
require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
require(to != address(0), "ERC721: transfer to the zero address");
_beforeTokenTransfer(from, to, tokenId);
_approve(address(0), tokenId);
_balances[from] -= 1;
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
_afterTokenTransfer(from, to, tokenId);
}
function _approve(address to, uint256 tokenId) internal virtual {
_tokenApprovals[tokenId] = to;
emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
}
function _setApprovalForAll(
address owner,
address operator,
bool approved
) internal virtual {
require(owner != operator, "ERC721: approve to caller");
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
function _checkOnERC721Received(
address from,
address to,
uint256 tokenId,
bytes memory _data
) private returns (bool) {
if (to.isContract()) {
try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {
return retval == IERC721Receiver.onERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
revert("ERC721: transfer to non ERC721Receiver implementer");
} else {
assembly {
revert(add(32, reason), mload(reason))
}
}
}
} else {
return true;
}
}
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual {}
function _afterTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual {}
}
文件 10 的 43:IABIResolver.sol
pragma solidity >=0.8.4;
import "./IABIResolver.sol";
import "../ResolverBase.sol";
interface IABIResolver {
event ABIChanged(bytes32 indexed node, uint256 indexed contentType);
function ABI(bytes32 node, uint256 contentTypes) external view returns (uint256, bytes memory);
}
文件 11 的 43:IAddrResolver.sol
pragma solidity >=0.8.4;
interface IAddrResolver {
event AddrChanged(bytes32 indexed node, address a);
function addr(bytes32 node) external view returns (address payable);
}
文件 12 的 43:IAddressResolver.sol
pragma solidity >=0.8.4;
interface IAddressResolver {
event AddressChanged(bytes32 indexed node, uint coinType, bytes newAddress);
function addr(bytes32 node, uint coinType) external view returns(bytes memory);
}
文件 13 的 43:IContentHashResolver.sol
pragma solidity >=0.8.4;
interface IContentHashResolver {
event ContenthashChanged(bytes32 indexed node, bytes hash);
function contenthash(bytes32 node) external view returns (bytes memory);
}
文件 14 的 43:IDNSRecordResolver.sol
pragma solidity >=0.8.4;
interface IDNSRecordResolver {
event DNSRecordChanged(bytes32 indexed node, bytes name, uint16 resource, bytes record);
event DNSRecordDeleted(bytes32 indexed node, bytes name, uint16 resource);
event DNSZoneCleared(bytes32 indexed node);
function dnsRecord(bytes32 node, bytes32 name, uint16 resource) external view returns (bytes memory);
}
文件 15 的 43:IDNSZoneResolver.sol
pragma solidity >=0.8.4;
interface IDNSZoneResolver {
event DNSZonehashChanged(bytes32 indexed node, bytes lastzonehash, bytes zonehash);
function zonehash(bytes32 node) external view returns (bytes memory);
}
文件 16 的 43:IERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 17 的 43: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);
}
文件 18 的 43:IERC721Metadata.sol
pragma solidity ^0.8.0;
import "../IERC721.sol";
interface IERC721Metadata is IERC721 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function tokenURI(uint256 tokenId) external view returns (string memory);
}
文件 19 的 43:IERC721Receiver.sol
pragma solidity ^0.8.0;
interface IERC721Receiver {
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}
文件 20 的 43:IExtensionAccess.sol
pragma solidity >=0.8.4;
interface IExtensionAccess {
function getOperator(uint256 tokenId) external view returns (address);
function getOwner(uint256 tokenId) external view returns (address);
function isApprovedOrOwner(address spender, uint256 tokenId) external view returns (bool);
}
文件 21 的 43:IExtensionPayee.sol
pragma solidity >=0.8.4;
interface IExtensionPayee {
function payeeOf(bytes32 node) external view returns (address);
}
文件 22 的 43:IInterfaceResolver.sol
pragma solidity >=0.8.4;
interface IInterfaceResolver {
event InterfaceChanged(bytes32 indexed node, bytes4 indexed interfaceID, address implementer);
function interfaceImplementer(bytes32 node, bytes4 interfaceID) external view returns (address);
}
文件 23 的 43:INameResolver.sol
pragma solidity >=0.8.4;
interface INameResolver {
event NameChanged(bytes32 indexed node, string name);
function name(bytes32 node) external view returns (string memory);
}
文件 24 的 43:IPriceOracle.sol
pragma solidity >=0.8.4;
interface IPriceOracle {
function price(string calldata name, uint expires, uint duration) external view returns(uint);
}
文件 25 的 43:IPubkeyResolver.sol
pragma solidity >=0.8.4;
interface IPubkeyResolver {
event PubkeyChanged(bytes32 indexed node, bytes32 x, bytes32 y);
function pubkey(bytes32 node) external view returns (bytes32 x, bytes32 y);
}
文件 26 的 43:ISupportsInterface.sol
pragma solidity ^0.8.4;
interface ISupportsInterface {
function supportsInterface(bytes4 interfaceID) external pure returns(bool);
}
文件 27 的 43:ITextResolver.sol
pragma solidity >=0.8.4;
interface ITextResolver {
event TextChanged(bytes32 indexed node, string indexed indexedKey, string key);
function text(bytes32 node, string calldata key) external view returns (string memory);
}
文件 28 的 43:IUniversalRegistrar.sol
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
interface IUniversalRegistrar is IERC721 {
event ControllerAdded(bytes32 node, address indexed controller);
event ControllerRemoved(bytes32 node, address indexed controller);
event NameRegistered(
bytes32 node,
bytes32 indexed label,
address indexed owner,
uint256 expires
);
event NameRenewed(bytes32 node, bytes32 indexed label, uint256 expires);
function addController(bytes32 node, address controller) external;
function removeController(bytes32 node, address controller) external;
function setResolver(bytes32 node, address resolver) external;
function nameExpires(uint256 id) external view returns (uint256);
function available(uint256 id) external view returns (bool);
function register(
bytes32 node,
bytes32 label,
address owner,
uint256 duration
) external returns (uint256);
function renew(bytes32 node, bytes32 label, uint256 duration) external returns (uint256);
function reclaim(bytes32 node, bytes32 label, address owner) external;
}
文件 29 的 43:NameStore.sol
pragma solidity >=0.8.4;
import "../universal/UniversalRegistrar.sol";
import "./Access.sol";
contract NameStore is Access {
mapping(uint256 => bytes32) public tokenToExtension;
mapping(uint256 => mapping(bytes32 => mapping(bytes32 => address))) public reservedNames;
mapping(bytes32 => uint256) public reservedNamesVersion;
mapping(bytes32 => bool) public registrationsPaused;
mapping(bytes32 => bytes) public metadata;
event NameReserved(bytes32 indexed node, string name, address recipient);
event ReservedNamesCleared(bytes32 indexed node);
event RegistrationsPauseChanged(bytes32 indexed node, bool paused);
event MetadataChanged(bytes32 indexed node);
constructor(UniversalRegistrar _registrar) Access(_registrar) {}
function parentOf(uint256 tokenId) external view returns (bytes32) {
return tokenToExtension[tokenId];
}
function adopt(bytes32 parent, bytes32 label) external {
uint256 tokenId = uint256(keccak256(abi.encodePacked(parent, label)));
tokenToExtension[tokenId] = parent;
}
function bulkAdopt(bytes32 parent, bytes32[] calldata labels) external {
for (uint i = 0; i < labels.length; i++) {
uint256 tokenId = uint256(keccak256(abi.encodePacked(parent, labels[i])));
tokenToExtension[tokenId] = parent;
}
}
function setMetadata(bytes32 node, bytes calldata _metadata) external nodeOperator(node) {
metadata[node] = _metadata;
emit MetadataChanged(node);
}
function reserved(bytes32 node, bytes32 label) external view returns (address) {
return reservedNames[reservedNamesVersion[node]][node][label];
}
function available(bytes32 node, bytes32 label) external view returns (bool) {
return reservedNames[reservedNamesVersion[node]][node][label] == address(0) && !registrationsPaused[node];
}
function pauseRegistrations(bytes32 node) external nodeOperator(node) {
registrationsPaused[node] = true;
emit RegistrationsPauseChanged(node, true);
}
function unpauseRegistrations(bytes32 node) external nodeOperator(node) {
registrationsPaused[node] = false;
emit RegistrationsPauseChanged(node, false);
}
function reserve(bytes32 node, string calldata name, address recipient) external {
require(isNodeApprovedOrOwner(node, msg.sender) ||
isNodeOperator(node, msg.sender) ||
registrar.controllers(node, msg.sender),
"caller is not a controller, owner or operator");
_reserve(node, name, recipient);
}
function _reserve(bytes32 node, string calldata name, address recipient) internal {
bytes32 label = keccak256(bytes(name));
reservedNames[reservedNamesVersion[node]][node][label] = recipient;
emit NameReserved(node, name, recipient);
}
function bulkReserve(bytes32 node, string[] calldata names, address[] calldata recipients) external nodeOperator(node) {
require(names.length == recipients.length, "names and recipients must have the same length");
for (uint i = 0; i < names.length; i++) {
bytes32 label = keccak256(bytes(names[i]));
reservedNames[reservedNamesVersion[node]][node][label] = recipients[i];
emit NameReserved(node, names[i], recipients[i]);
}
}
function clearReservedNames(bytes32 node) external nodeOperator(node) {
reservedNamesVersion[node]++;
emit ReservedNamesCleared(node);
}
}
文件 30 的 43: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());
}
function owner() public view virtual returns (address) {
return _owner;
}
modifier onlyOwner() {
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);
}
}
文件 31 的 43:PremiumPriceOracle.sol
pragma solidity ^0.8.4;
import "./SafeMath.sol";
import "./StringUtils.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "./StablePriceOracle.sol";
import "../universal/UniversalRegistrar.sol";
import "./SLDPriceOracle.sol";
import "../universal_v2/Access.sol";
contract PremiumPriceOracle is Ownable, Access {
using SafeMath for *;
using StringUtils for *;
AggregatorInterface public immutable usdOracle;
SLDPriceOracle public sldPriceOracle;
uint256[] public defaultPrices;
mapping(bytes32 => uint256[]) public rentPrices;
mapping(bytes32 => uint256) public rentPricesUpdated;
mapping(uint256 => mapping(bytes32 => mapping(bytes32 => uint256))) public premiumPrices;
mapping(bytes32 => uint256) public premiumPricesVersion;
event NamePremium(bytes32 indexed node, string name, uint256 price);
event PremiumsCleared(bytes32 indexed node);
event RentPriceChanged(bytes32 node, uint256[] prices);
event DefaultRentPriceChanged(uint256[] prices);
bytes4 private constant INTERFACE_META_ID =
bytes4(keccak256("supportsInterface(bytes4)"));
bytes4 private constant ORACLE_ID =
bytes4(keccak256("price(bytes32,string,uint256,uint256)"));
constructor(SLDPriceOracle _sldPriceOracle, uint256[] memory _defaultPrices) Access(_sldPriceOracle.registrar()) {
usdOracle = _sldPriceOracle.usdOracle();
sldPriceOracle = _sldPriceOracle;
_setDefaultPrices(_defaultPrices);
}
function price(bytes32 node, string calldata name, uint256 expires, uint256 duration) external view returns (uint256) {
bytes32 label = keccak256(bytes(name));
if (premiumPrices[premiumPricesVersion[node]][node][label] != 0) {
uint256 basePremium = premiumPrices[premiumPricesVersion[node]][node][label];
return attoUSDToWei(basePremium.mul(duration));
}
if (rentPricesUpdated[node] == 0) {
return sldPriceOracle.price(node, name, expires, duration);
}
uint256 len = name.strlen();
uint256[] memory prices = rentPrices[node].length > 0 ? rentPrices[node] : defaultPrices;
if (len > prices.length) {
len = prices.length;
}
require(len > 0);
uint256 basePrice = prices[len - 1].mul(duration);
return attoUSDToWei(basePrice);
}
function attoUSDToWei(uint256 amount) internal view returns (uint256) {
uint256 ethPrice = uint256(usdOracle.latestAnswer());
return amount.mul(1e8).div(ethPrice);
}
function weiToAttoUSD(uint256 amount) internal view returns (uint256) {
uint256 ethPrice = uint256(usdOracle.latestAnswer());
return amount.mul(ethPrice).div(1e8);
}
function premium(bytes32 node, bytes32 label) external view returns (uint256) {
return premiumPrices[premiumPricesVersion[node]][node][label];
}
function setPremium(bytes32 node, string calldata name, uint256 _price) external nodeOperator(node) {
bytes32 label = keccak256(bytes(name));
premiumPrices[premiumPricesVersion[node]][node][label] = _price;
emit NamePremium(node, name, _price);
}
function setPremiums(bytes32 node, string[] calldata names, uint256[] calldata prices) external nodeOperator(node) {
require(names.length == prices.length, "names and prices must have the same length");
for (uint i = 0; i < names.length; i++) {
bytes32 label = keccak256(bytes(names[i]));
premiumPrices[premiumPricesVersion[node]][node][label] = prices[i];
emit NamePremium(node, names[i], prices[i]);
}
}
function clearPremiums(bytes32 node) external nodeOperator(node) {
premiumPricesVersion[node]++;
emit PremiumsCleared(node);
}
function setPrices(bytes32 node, uint256[] memory _rentPrices) public nodeOperator(node) {
require(block.timestamp - rentPricesUpdated[node] > 5 minutes);
rentPrices[node] = _rentPrices;
rentPricesUpdated[node] = block.timestamp;
emit RentPriceChanged(node, _rentPrices);
}
function setDefaultPrices(uint256[] memory _defaultPrices) public onlyOwner {
_setDefaultPrices(_defaultPrices);
}
function _setDefaultPrices(uint256[] memory _defaultPrices) internal {
defaultPrices = _defaultPrices;
emit DefaultRentPriceChanged(_defaultPrices);
}
function supportsInterface(bytes4 interfaceID) public view virtual returns (bool)
{
return interfaceID == INTERFACE_META_ID || interfaceID == ORACLE_ID;
}
}
文件 32 的 43:RegistrarAccess.sol
pragma solidity ^0.8.4;
import "../root/Root.sol";
contract RegistrarAccess {
event NodeOwnerChanged(bytes32 node, address indexed oldOwner, address indexed newOwner);
event RegistryControllersChanged(address indexed controller, bool approved);
event RegistryNodeControllersChanged(bytes32 node, address indexed controller, bool approved);
Root public root;
constructor(Root _root) {
root = _root;
}
mapping(bytes32 => address) private nodeOwners;
mapping(address => bool) private registryControllers;
mapping(bytes32 => mapping(address => bool)) private registryNodeControllers;
modifier onlyNodeOwner(bytes32 node) {
require(nodeOwners[node] == msg.sender);
_;
}
modifier onlyRegistry {
require(root.controllers(msg.sender));
_;
}
modifier onlyRegistryControllers(bytes32 node, address controller) {
require(registryNodeControllers[node][controller] ||
registryControllers[controller], "controller not approved by registry");
_;
}
function transferNodeOwnership(bytes32 node, address newOwner) public onlyNodeOwner(node) {
require(newOwner != address(0));
emit NodeOwnerChanged(node, nodeOwners[node], newOwner);
nodeOwners[node] = newOwner;
}
function renounceNodeOwnership(bytes32 node) public onlyNodeOwner(node) {
emit NodeOwnerChanged(node, nodeOwners[node], address(0));
nodeOwners[node] = address(0);
}
function ownerOfNode(bytes32 node) public view returns (address) {
return nodeOwners[node];
}
function setSubnodeOwner(bytes32 label, address owner) public onlyRegistry returns(bytes32) {
require(!root.locked(label), "name locked");
bytes32 node = keccak256(abi.encodePacked(bytes32(0), label));
emit NodeOwnerChanged(node, nodeOwners[node], owner);
nodeOwners[node] = owner;
return node;
}
function approveControllerForNode(bytes32 node, address controller, bool approved) external onlyRegistry {
registryNodeControllers[node][controller] = approved;
emit RegistryNodeControllersChanged(node, controller, approved);
}
function approveController(address controller, bool approved) external onlyRegistry {
registryControllers[controller] = approved;
emit RegistryControllersChanged(controller, approved);
}
}
文件 33 的 43:Resolver.sol
pragma solidity >=0.8.4;
import "./profiles/IABIResolver.sol";
import "./profiles/IAddressResolver.sol";
import "./profiles/IAddrResolver.sol";
import "./profiles/IContentHashResolver.sol";
import "./profiles/IDNSRecordResolver.sol";
import "./profiles/IDNSZoneResolver.sol";
import "./profiles/IInterfaceResolver.sol";
import "./profiles/INameResolver.sol";
import "./profiles/IPubkeyResolver.sol";
import "./profiles/ITextResolver.sol";
import "./ISupportsInterface.sol";
interface Resolver is ISupportsInterface, IABIResolver, IAddressResolver, IAddrResolver, IContentHashResolver, IDNSRecordResolver, IDNSZoneResolver, IInterfaceResolver, INameResolver, IPubkeyResolver, ITextResolver {
event ContentChanged(bytes32 indexed node, bytes32 hash);
function setABI(bytes32 node, uint256 contentType, bytes calldata data) external;
function setAddr(bytes32 node, address addr) external;
function setAddr(bytes32 node, uint coinType, bytes calldata a) external;
function setContenthash(bytes32 node, bytes calldata hash) external;
function setDnsrr(bytes32 node, bytes calldata data) external;
function setName(bytes32 node, string calldata _name) external;
function setPubkey(bytes32 node, bytes32 x, bytes32 y) external;
function setText(bytes32 node, string calldata key, string calldata value) external;
function setInterface(bytes32 node, bytes4 interfaceID, address implementer) external;
function multicall(bytes[] calldata data) external returns(bytes[] memory results);
function content(bytes32 node) external view returns (bytes32);
function multihash(bytes32 node) external view returns (bytes memory);
function setContent(bytes32 node, bytes32 hash) external;
function setMultihash(bytes32 node, bytes calldata hash) external;
}
文件 34 的 43:ResolverBase.sol
pragma solidity >=0.8.4;
import "./SupportsInterface.sol";
abstract contract ResolverBase is SupportsInterface {
function isAuthorised(bytes32 node) internal virtual view returns(bool);
modifier authorised(bytes32 node) {
require(isAuthorised(node));
_;
}
}
文件 35 的 43:Root.sol
pragma solidity ^0.8.4;
import "@ensdomains/ens-contracts/contracts/registry/ENS.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "./Controllable.sol";
contract Root is Ownable, Controllable {
bytes32 private constant ROOT_NODE = bytes32(0);
bytes4 private constant INTERFACE_META_ID =
bytes4(keccak256("supportsInterface(bytes4)"));
event TLDLocked(bytes32 indexed label);
ENS public ens;
mapping(bytes32 => bool) public locked;
constructor(ENS _ens) {
ens = _ens;
}
function setSubnodeOwner(bytes32 label, address owner) external onlyController
{
require(!locked[label], "name locked");
ens.setSubnodeOwner(ROOT_NODE, label, owner);
}
function setResolver(address resolver) external onlyController {
ens.setResolver(ROOT_NODE, resolver);
}
function lock(bytes32 label) external onlyController {
emit TLDLocked(label);
locked[label] = true;
}
function supportsInterface(bytes4 interfaceID) external pure returns (bool) {
return interfaceID == INTERFACE_META_ID;
}
}
文件 36 的 43:SLDPriceOracle.sol
pragma solidity ^0.8.4;
import "./SafeMath.sol";
import "./StringUtils.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "./StablePriceOracle.sol";
import "../universal/UniversalRegistrar.sol";
contract SLDPriceOracle is Ownable {
using SafeMath for *;
using StringUtils for *;
mapping(bytes32 => uint256[]) public rentPrices;
uint256[] public defaultPrices;
AggregatorInterface public immutable usdOracle;
UniversalRegistrar public registrar;
modifier onlyNodeOwner(bytes32 node) {
require(registrar.ownerOfNode(node) == _msgSender(), "caller is not the node owner");
_;
}
event OracleChanged(address oracle);
event RentPriceChanged(bytes32 node, uint256[] prices);
event DefaultRentPriceChanged(uint256[] prices);
bytes4 private constant INTERFACE_META_ID =
bytes4(keccak256("supportsInterface(bytes4)"));
bytes4 private constant ORACLE_ID =
bytes4(keccak256("price(bytes32,string,uint256,uint256)"));
constructor(UniversalRegistrar _registrar, AggregatorInterface _usdOracle, uint256[] memory _defaultPrices) {
registrar = _registrar;
usdOracle = _usdOracle;
defaultPrices = _defaultPrices;
}
function price(bytes32 node, string calldata name, uint256 expires, uint256 duration) external view returns (uint256) {
uint256 len = name.strlen();
uint256[] memory prices = rentPrices[node].length > 0 ? rentPrices[node] : defaultPrices;
if (len > prices.length) {
len = prices.length;
}
require(len > 0);
uint256 basePrice = prices[len - 1].mul(duration);
return attoUSDToWei(basePrice);
}
function setPrices(bytes32 node, uint256[] memory _rentPrices) public onlyNodeOwner(node) {
rentPrices[node] = _rentPrices;
emit RentPriceChanged(node, _rentPrices);
}
function setDefaultPrices(uint256[] memory _defaultPrices) public onlyOwner {
defaultPrices = _defaultPrices;
emit DefaultRentPriceChanged(_defaultPrices);
}
function attoUSDToWei(uint256 amount) internal view returns (uint256) {
uint256 ethPrice = uint256(usdOracle.latestAnswer());
return amount.mul(1e8).div(ethPrice);
}
function weiToAttoUSD(uint256 amount) internal view returns (uint256) {
uint256 ethPrice = uint256(usdOracle.latestAnswer());
return amount.mul(ethPrice).div(1e8);
}
function supportsInterface(bytes4 interfaceID) public view virtual returns (bool)
{
return interfaceID == INTERFACE_META_ID || interfaceID == ORACLE_ID;
}
}
文件 37 的 43:SafeMath.sol
pragma solidity >=0.8.4;
library SafeMath {
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b);
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0);
uint256 c = a / b;
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a);
uint256 c = a - b;
return c;
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a);
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0);
return a % b;
}
}
文件 38 的 43:StablePriceOracle.sol
pragma solidity ^0.8.4;
import "./IPriceOracle.sol";
import "./SafeMath.sol";
import "./StringUtils.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
interface AggregatorInterface {
function latestAnswer() external view returns (int256);
}
contract StablePriceOracle is Ownable, IPriceOracle {
using SafeMath for *;
using StringUtils for *;
uint256[] public rentPrices;
AggregatorInterface public immutable usdOracle;
event OracleChanged(address oracle);
event RentPriceChanged(uint256[] prices);
bytes4 private constant INTERFACE_META_ID =
bytes4(keccak256("supportsInterface(bytes4)"));
bytes4 private constant ORACLE_ID =
bytes4(
keccak256("price(string,uint256,uint256)") ^
keccak256("premium(string,uint256,uint256)")
);
constructor(AggregatorInterface _usdOracle, uint256[] memory _rentPrices) {
usdOracle = _usdOracle;
setPrices(_rentPrices);
}
function price(string calldata name, uint256 expires, uint256 duration) external view override returns (uint256) {
uint256 len = name.strlen();
if (len > rentPrices.length) {
len = rentPrices.length;
}
require(len > 0);
uint256 basePrice = rentPrices[len - 1].mul(duration);
basePrice = basePrice.add(_premium(name, expires, duration));
return attoUSDToWei(basePrice);
}
function setPrices(uint256[] memory _rentPrices) public onlyOwner {
rentPrices = _rentPrices;
emit RentPriceChanged(_rentPrices);
}
function premium(
string calldata name,
uint256 expires,
uint256 duration
) external view returns (uint256) {
uint256 weiPrice = attoUSDToWei(_premium(name, expires, duration));
return weiPrice;
}
function _premium(
string memory name,
uint256 expires,
uint256 duration
) internal view virtual returns (uint256) {
return 0;
}
function attoUSDToWei(uint256 amount) internal view returns (uint256) {
uint256 ethPrice = uint256(usdOracle.latestAnswer());
return amount.mul(1e8).div(ethPrice);
}
function weiToAttoUSD(uint256 amount) internal view returns (uint256) {
uint256 ethPrice = uint256(usdOracle.latestAnswer());
return amount.mul(ethPrice).div(1e8);
}
function supportsInterface(bytes4 interfaceID) public view virtual returns (bool)
{
return interfaceID == INTERFACE_META_ID || interfaceID == ORACLE_ID;
}
}
文件 39 的 43:StringUtils.sol
pragma solidity >=0.8.4;
library StringUtils {
function strlen(string memory s) internal pure returns (uint) {
uint len;
uint i = 0;
uint bytelength = bytes(s).length;
for(len = 0; i < bytelength; len++) {
bytes1 b = bytes(s)[i];
if(b < 0x80) {
i += 1;
} else if (b < 0xE0) {
i += 2;
} else if (b < 0xF0) {
i += 3;
} else if (b < 0xF8) {
i += 4;
} else if (b < 0xFC) {
i += 5;
} else {
i += 6;
}
}
return len;
}
}
文件 40 的 43:Strings.sol
pragma solidity ^0.8.0;
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
function toString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
}
文件 41 的 43:SupportsInterface.sol
pragma solidity ^0.8.4;
import "./ISupportsInterface.sol";
abstract contract SupportsInterface is ISupportsInterface {
function supportsInterface(bytes4 interfaceID) virtual override public pure returns(bool) {
return interfaceID == type(ISupportsInterface).interfaceId;
}
}
文件 42 的 43:UniversalRegistrar.sol
pragma solidity ^0.8.4;
import "@ensdomains/ens-contracts/contracts/registry/ENS.sol";
import "@ensdomains/ens-contracts/contracts/registry/ENSRegistry.sol";
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "./IUniversalRegistrar.sol";
import "./RegistrarAccess.sol";
contract UniversalRegistrar is ERC721, RegistrarAccess, IUniversalRegistrar, Ownable {
mapping(uint256 => uint) expiries;
ENS public ens;
string private metadataUri;
mapping(bytes32 => mapping(address => bool)) public controllers;
uint256 public constant GRACE_PERIOD = 90 days;
bytes4 constant private INTERFACE_META_ID = bytes4(keccak256("supportsInterface(bytes4)"));
bytes4 constant private ERC721_ID = bytes4(
keccak256("balanceOf(address)") ^
keccak256("ownerOf(uint256)") ^
keccak256("approve(address,uint256)") ^
keccak256("getApproved(uint256)") ^
keccak256("setApprovalForAll(address,bool)") ^
keccak256("isApprovedForAll(address,address)") ^
keccak256("transferFrom(address,address,uint256)") ^
keccak256("safeTransferFrom(address,address,uint256)") ^
keccak256("safeTransferFrom(address,address,uint256,bytes)")
);
bytes4 constant private RECLAIM_ID = bytes4(keccak256("reclaim(bytes32,uint256,address)"));
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view override returns (bool) {
address owner = ownerOf(tokenId);
return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
}
constructor(ENS _ens, Root _root) ERC721("Impervious Registry", "IR") RegistrarAccess(_root) {
ens = _ens;
}
function _baseURI() internal view virtual override returns (string memory) {
return metadataUri;
}
modifier live(bytes32 node) {
require(ens.owner(node) == address(this));
_;
}
modifier onlyController(bytes32 node) {
require(controllers[node][msg.sender]);
_;
}
function ownerOf(uint256 tokenId) public view override(IERC721, ERC721) returns (address) {
require(expiries[tokenId] > block.timestamp);
return super.ownerOf(tokenId);
}
function setUri(string memory _uri) external onlyOwner {
metadataUri = _uri;
}
function addController(
bytes32 node,
address controller
) external override onlyNodeOwner(node) onlyRegistryControllers(node, controller) {
controllers[node][controller] = true;
emit ControllerAdded(node, controller);
}
function removeController(bytes32 node, address controller) external override onlyNodeOwner(node) {
controllers[node][controller] = false;
emit ControllerRemoved(node, controller);
}
function setResolver(bytes32 node, address resolver) external override onlyNodeOwner(node) {
ens.setResolver(node, resolver);
}
function nameExpires(uint256 id) external view override returns (uint) {
return expiries[id];
}
function available(uint256 id) public view override returns (bool) {
return expiries[id] + GRACE_PERIOD < block.timestamp;
}
function register(bytes32 node, bytes32 label, address owner, uint duration) external override returns (uint) {
return _register(node, label, owner, duration, true);
}
function registerOnly(bytes32 node, bytes32 label, address owner, uint duration) external returns (uint) {
return _register(node, label, owner, duration, false);
}
function _register(bytes32 node, bytes32 label, address owner,
uint duration, bool updateRegistry) internal live(node) onlyController(node) returns (uint) {
require(block.timestamp + duration + GRACE_PERIOD > block.timestamp + GRACE_PERIOD);
uint256 id = _tokenID(node, label);
require(available(id));
expiries[id] = block.timestamp + duration;
if (_exists(id)) {
_burn(id);
}
_mint(owner, id);
if (updateRegistry) {
ens.setSubnodeOwner(node, label, owner);
}
emit NameRegistered(node, label, owner, block.timestamp + duration);
return block.timestamp + duration;
}
function renew(bytes32 node, bytes32 label, uint duration) external override live(node) onlyController(node) returns (uint) {
uint256 id = _tokenID(node, label);
require(expiries[id] + GRACE_PERIOD >= block.timestamp);
require(expiries[id] + duration + GRACE_PERIOD > duration + GRACE_PERIOD);
expiries[id] += duration;
emit NameRenewed(node, label, expiries[id]);
return expiries[id];
}
function reclaim(bytes32 node, bytes32 label, address owner) external override live(node) {
uint256 id = _tokenID(node, label);
require(_isApprovedOrOwner(msg.sender, id));
ens.setSubnodeOwner(node, label, owner);
}
function supportsInterface(bytes4 interfaceID) public override(ERC721, IERC165) view returns (bool) {
return interfaceID == INTERFACE_META_ID ||
interfaceID == ERC721_ID ||
interfaceID == RECLAIM_ID;
}
function _tokenID(bytes32 node, bytes32 label) internal pure returns (uint256) {
return uint256(keccak256(abi.encodePacked(node, label)));
}
}
文件 43 的 43:UniversalRegistrarControllerV3.sol
pragma solidity >=0.8.4;
import "@ensdomains/ens-contracts/contracts/resolvers/Resolver.sol";
import "../common/StringUtils.sol";
import "../common/PremiumPriceOracle.sol";
import "../universal_v2/NameStore.sol";
import "../universal_v2/BaseUniversalRegistrarControllerV2.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract UniversalRegistrarControllerV3 is Ownable, BaseUniversalRegistrarControllerV2, Access {
using StringUtils for *;
uint constant public MIN_REGISTRATION_DURATION = 28 days;
bytes4 constant private INTERFACE_META_ID = bytes4(keccak256("supportsInterface(bytes4)"));
bytes4 constant private COMMITMENT_CONTROLLER_ID = bytes4(
keccak256("rentPrice(bytes32,string,uint256)") ^
keccak256("available(bytes32,string)") ^
keccak256("makeCommitment(bytes32,string,address,bytes32)") ^
keccak256("commit(bytes32)") ^
keccak256("register(bytes32,string,address,uint256,bytes32)") ^
keccak256("renew(bytes32,string,uint256)")
);
bytes4 constant private REGISTER_NOW_CONTROLLER_ID = bytes4(
keccak256("registerNow(bytes32,string,address,uint,address,address)")
);
bytes4 constant private COMMITMENT_WITH_CONFIG_CONTROLLER_ID = bytes4(
keccak256("registerWithConfig(bytes32,string,address,uint256,bytes32,address,address)") ^
keccak256("makeCommitmentWithConfig(bytes32,string,address,bytes32,address,address)")
);
bytes4 constant private RESERVED_NAMES_CONTROLLER_ID = bytes4(
keccak256("registerReservedWithConfig(bytes32,string,address,uint256,address,address)") ^
keccak256("availabilityInfo(bytes32,string)")
);
PremiumPriceOracle prices;
NameStore store;
uint public minCommitmentAge;
uint public maxCommitmentAge;
mapping(bytes32 => uint) public commitments;
mapping(bytes32 => bool) public requireCommitReveal;
event NameRegistered(bytes32 indexed tld, string name, bytes32 indexed label, address indexed owner, uint cost, uint expires);
event NameRenewed(bytes32 indexed tld, string name, bytes32 indexed label, uint cost, uint expires);
event NewPriceOracle(address indexed oracle);
constructor(
UniversalRegistrar base_,
PremiumPriceOracle prices_,
NameStore store_,
uint minCommitmentAge_,
uint maxCommitmentAge_,
uint256 ownerShare_,
uint256 registryShare_
) BaseUniversalRegistrarControllerV2(base_, ownerShare_, registryShare_) Access(base_) {
require(maxCommitmentAge_ > minCommitmentAge_);
store = store_;
prices = prices_;
minCommitmentAge = minCommitmentAge_;
maxCommitmentAge = maxCommitmentAge_;
}
function _tokenID(bytes32 node, bytes32 label) internal pure returns (uint256) {
return uint256(keccak256(abi.encodePacked(node, label)));
}
function rentPrice(bytes32 node, string memory name, uint duration) view public returns (uint) {
bytes32 label = keccak256(bytes(name));
return prices.price(node, name, base.nameExpires(_tokenID(node, label)), duration);
}
function valid(string memory name) public pure returns (bool) {
return name.strlen() >= 1;
}
function available(bytes32 node, string memory name) public view returns (bool) {
bytes32 label = keccak256(bytes(name));
return _available(node, name, label) && store.available(node, label);
}
function _available(bytes32 node, string memory name, bytes32 label) internal view returns (bool) {
return valid(name) && base.available(_tokenID(node, label));
}
function availabilityInfo(bytes32 node, string memory name) public view returns (uint8, address) {
bytes32 label = keccak256(bytes(name));
if (!valid(name) ||
!base.available(_tokenID(node, label))) {
return (0, address(0));
}
if (store.reserved(node, label) != address(0)) {
return (2, store.reserved(node, label));
}
if (store.registrationsPaused(node)) {
return (3, address(0));
}
return (1, address(0));
}
function makeCommitment(bytes32 node, string memory name, address owner, bytes32 secret) pure public returns (bytes32) {
return makeCommitmentWithConfig(node, name, owner, secret, address(0), address(0));
}
function makeCommitmentWithConfig(bytes32 node, string memory name,
address owner, bytes32 secret, address resolver, address addr) pure public returns (bytes32) {
bytes32 label = keccak256(bytes(name));
return _makeCommitmentWithConfig(node, label, owner, secret, resolver, addr);
}
function _makeCommitmentWithConfig(bytes32 node, bytes32 label,
address owner, bytes32 secret, address resolver, address addr) pure internal returns (bytes32) {
if (resolver == address(0) && addr == address(0)) {
return keccak256(abi.encodePacked(node, label, owner, secret));
}
require(resolver != address(0));
return keccak256(abi.encodePacked(node, label, owner, resolver, addr, secret));
}
function commit(bytes32 commitment) public {
require(commitments[commitment] + maxCommitmentAge < block.timestamp);
commitments[commitment] = block.timestamp;
}
function register(bytes32 node, string calldata name, address owner, uint duration, bytes32 secret) external payable {
registerWithConfig(node, name, owner, duration, secret, address(0), address(0));
}
function registerWithConfig(bytes32 node, string memory name, address owner,
uint duration, bytes32 secret, address resolver, address addr) public payable {
bytes32 label = keccak256(bytes(name));
uint cost = _consumeCommitment
(
node,
name,
label,
duration,
_makeCommitmentWithConfig(node, label, owner, secret, resolver, addr)
);
store.adopt(node, label);
uint expires;
if (resolver != address(0)) {
expires = base.register(node, label, address(this), duration);
bytes32 nodehash = keccak256(abi.encodePacked(node, label));
base.ens().setResolver(nodehash, resolver);
if (addr != address(0)) {
Resolver(resolver).setAddr(nodehash, addr);
}
base.reclaim(node, label, owner);
base.transferFrom(address(this), owner, uint256(nodehash));
} else {
require(addr == address(0));
expires = base.register(node, label, owner, duration);
}
_addPayment(node, cost);
emit NameRegistered(node, name, label, owner, cost, expires);
if (msg.value > cost) {
payable(msg.sender).transfer(msg.value - cost);
}
}
function registerReservedWithConfig(bytes32 node, string memory name, address owner,
uint duration, address resolver, address addr) public payable {
bytes32 label = keccak256(bytes(name));
require(_available(node, name, label) && !store.registrationsPaused(node));
require(store.reserved(node, label) == msg.sender, "unauthorised to register reserved name");
uint cost = rentPrice(node, name, duration);
require(duration >= MIN_REGISTRATION_DURATION);
require(msg.value >= cost);
store.adopt(node, label);
store.reserve(node, name, address(0));
uint expires;
if (resolver != address(0)) {
expires = base.register(node, label, address(this), duration);
bytes32 nodehash = keccak256(abi.encodePacked(node, label));
base.ens().setResolver(nodehash, resolver);
if (addr != address(0)) {
Resolver(resolver).setAddr(nodehash, addr);
}
base.reclaim(node, label, owner);
base.transferFrom(address(this), owner, uint256(nodehash));
} else {
require(addr == address(0));
expires = base.register(node, label, owner, duration);
}
_addPayment(node, cost);
emit NameRegistered(node, name, label, owner, cost, expires);
if (msg.value > cost) {
payable(msg.sender).transfer(msg.value - cost);
}
}
function setRequireCommitReveal(bytes32 node, bool required) public nodeOperator(node) {
requireCommitReveal[node] = required;
}
function registerNow(bytes32 node, string memory name, address owner,
uint duration, address resolver, address addr) public payable {
require(!requireCommitReveal[node], "this node requires commit-reveal");
bytes32 label = keccak256(bytes(name));
require(_available(node, name, label) && store.available(node, label));
uint cost = rentPrice(node, name, duration);
require(duration >= MIN_REGISTRATION_DURATION);
require(msg.value >= cost, "insufficient funds");
store.adopt(node, label);
uint expires;
if (resolver != address(0)) {
expires = base.register(node, label, address(this), duration);
bytes32 nodehash = keccak256(abi.encodePacked(node, label));
base.ens().setResolver(nodehash, resolver);
if (addr != address(0)) {
Resolver(resolver).setAddr(nodehash, addr);
}
base.reclaim(node, label, owner);
base.transferFrom(address(this), owner, uint256(nodehash));
} else {
require(addr == address(0));
expires = base.register(node, label, owner, duration);
}
_addPayment(node, cost);
emit NameRegistered(node, name, label, owner, cost, expires);
if (msg.value > cost) {
payable(msg.sender).transfer(msg.value - cost);
}
}
function renew(bytes32 node, string calldata name, uint duration) external payable {
uint cost = rentPrice(node, name, duration);
require(msg.value >= cost);
bytes32 label = keccak256(bytes(name));
uint expires = base.renew(node, label, duration);
_addPayment(node, cost);
emit NameRenewed(node, name, label, cost, expires);
if (msg.value > cost) {
payable(msg.sender).transfer(msg.value - cost);
}
}
function supportsInterface(bytes4 interfaceID) external pure returns (bool) {
return interfaceID == INTERFACE_META_ID ||
interfaceID == COMMITMENT_CONTROLLER_ID ||
interfaceID == COMMITMENT_WITH_CONFIG_CONTROLLER_ID ||
interfaceID == RESERVED_NAMES_CONTROLLER_ID ||
interfaceID == REGISTER_NOW_CONTROLLER_ID;
}
function _consumeCommitment(bytes32 node, string memory name, bytes32 label, uint duration, bytes32 commitment) internal returns (uint256) {
require(commitments[commitment] + minCommitmentAge <= block.timestamp);
require(commitments[commitment] + maxCommitmentAge > block.timestamp);
require(_available(node, name, label) && store.available(node, label));
delete (commitments[commitment]);
uint cost = rentPrice(node, name, duration);
require(duration >= MIN_REGISTRATION_DURATION);
require(msg.value >= cost);
return cost;
}
}
{
"compilationTarget": {
"src/universal_v3/UniversalRegistrarControllerV3.sol": "UniversalRegistrarControllerV3"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 10000
},
"remappings": []
}
[{"inputs":[{"internalType":"contract UniversalRegistrar","name":"base_","type":"address"},{"internalType":"contract PremiumPriceOracle","name":"prices_","type":"address"},{"internalType":"contract NameStore","name":"store_","type":"address"},{"internalType":"uint256","name":"minCommitmentAge_","type":"uint256"},{"internalType":"uint256","name":"maxCommitmentAge_","type":"uint256"},{"internalType":"uint256","name":"ownerShare_","type":"uint256"},{"internalType":"uint256","name":"registryShare_","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"tld","type":"bytes32"},{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":true,"internalType":"bytes32","name":"label","type":"bytes32"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"cost","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"expires","type":"uint256"}],"name":"NameRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"tld","type":"bytes32"},{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":true,"internalType":"bytes32","name":"label","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"cost","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"expires","type":"uint256"}],"name":"NameRenewed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oracle","type":"address"}],"name":"NewPriceOracle","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":false,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PaymentReleased","type":"event"},{"inputs":[],"name":"MIN_REGISTRATION_DURATION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"name","type":"string"}],"name":"availabilityInfo","outputs":[{"internalType":"uint8","name":"","type":"uint8"},{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"name","type":"string"}],"name":"available","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"balance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"base","outputs":[{"internalType":"contract UniversalRegistrar","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"commitment","type":"bytes32"}],"name":"commit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"commitments","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"address","name":"operator","type":"address"}],"name":"isNodeApprovedOrOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"address","name":"operator","type":"address"}],"name":"isNodeOperator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"name","type":"string"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"bytes32","name":"secret","type":"bytes32"}],"name":"makeCommitment","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"name","type":"string"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"bytes32","name":"secret","type":"bytes32"},{"internalType":"address","name":"resolver","type":"address"},{"internalType":"address","name":"addr","type":"address"}],"name":"makeCommitmentWithConfig","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"maxCommitmentAge","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minCommitmentAge","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"ownerBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"ownerPayee","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"ownerReleased","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ownerShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"name","type":"string"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"bytes32","name":"secret","type":"bytes32"}],"name":"register","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"name","type":"string"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"address","name":"resolver","type":"address"},{"internalType":"address","name":"addr","type":"address"}],"name":"registerNow","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"name","type":"string"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"address","name":"resolver","type":"address"},{"internalType":"address","name":"addr","type":"address"}],"name":"registerReservedWithConfig","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"name","type":"string"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"bytes32","name":"secret","type":"bytes32"},{"internalType":"address","name":"resolver","type":"address"},{"internalType":"address","name":"addr","type":"address"}],"name":"registerWithConfig","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"registrar","outputs":[{"internalType":"contract UniversalRegistrar","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"registryBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"registryPayee","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"registryReleased","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"registryShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"releaseToOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"releaseToRegistry","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"duration","type":"uint256"}],"name":"renew","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"duration","type":"uint256"}],"name":"rentPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"requireCommitReveal","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bool","name":"required","type":"bool"}],"name":"setRequireCommitReveal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceID","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"totalReleased","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"name","type":"string"}],"name":"valid","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"}]