Source Code
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Cross-Chain Transactions
Loading...
Loading
Contract Name:
FNSOwnedResolver
Compiler Version
v0.8.21+commit.d9974bed
Optimization Enabled:
Yes with 1300 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.19;
// ====================================================================
// | ______ _______ |
// | / _____________ __ __ / ____(_____ ____ _____ ________ |
// | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ |
// | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ |
// | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ |
// | |
// ====================================================================
// ======================= FNS OwnedResolver ==========================
// ====================================================================
// Frax Finance: https://github.com/FraxFinance
import { ENSRegistry } from "ens-contracts/contracts/registry/ENSRegistry.sol";
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import { OwnedResolver } from "ens-contracts/contracts/resolvers/OwnedResolver.sol";
contract FNSOwnedResolver is OwnedResolver {
bytes32 private constant FRAX_NODE = 0x323752ac646b7763acccb86343b9898c911d0ef2f83fd5707e526976b8eaea1c;
string public constant name = "FNS Owned Resolver";
constructor(address delegationRegistry, address initialDelegate) OwnedResolver() {
delegationRegistry.call(abi.encodeWithSignature("setDelegationForSelf(address)", initialDelegate));
delegationRegistry.call(abi.encodeWithSignature("disableSelfManagingDelegations()"));
delegationRegistry.call(abi.encodeWithSignature("disableDelegationManagement()"));
}
}pragma solidity >=0.8.4;
import "./ENS.sol";
/**
* The ENS registry contract.
*/
contract ENSRegistry is ENS {
struct Record {
address owner;
address resolver;
uint64 ttl;
}
mapping(bytes32 => Record) records;
mapping(address => mapping(address => bool)) operators;
// Permits modifications only by the owner of the specified node.
modifier authorised(bytes32 node) {
address owner = records[node].owner;
require(owner == msg.sender || operators[owner][msg.sender]);
_;
}
/**
* @dev Constructs a new ENS registry.
*/
constructor() public {
records[0x0].owner = msg.sender;
}
/**
* @dev Sets the record for a node.
* @param node The node to update.
* @param owner The address of the new owner.
* @param resolver The address of the resolver.
* @param ttl The TTL in seconds.
*/
function setRecord(
bytes32 node,
address owner,
address resolver,
uint64 ttl
) external virtual override {
setOwner(node, owner);
_setResolverAndTTL(node, resolver, ttl);
}
/**
* @dev Sets the record for a subnode.
* @param node The parent node.
* @param label The hash of the label specifying the subnode.
* @param owner The address of the new owner.
* @param resolver The address of the resolver.
* @param ttl The TTL in seconds.
*/
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);
}
/**
* @dev Transfers ownership of a node to a new address. May only be called by the current owner of the node.
* @param node The node to transfer ownership of.
* @param owner The address of the new owner.
*/
function setOwner(
bytes32 node,
address owner
) public virtual override authorised(node) {
_setOwner(node, owner);
emit Transfer(node, owner);
}
/**
* @dev Transfers ownership of a subnode keccak256(node, label) to a new address. May only be called by the owner of the parent node.
* @param node The parent node.
* @param label The hash of the label specifying the subnode.
* @param owner The address of the new owner.
*/
function setSubnodeOwner(
bytes32 node,
bytes32 label,
address owner
) public virtual override authorised(node) returns (bytes32) {
bytes32 subnode = keccak256(abi.encodePacked(node, label));
_setOwner(subnode, owner);
emit NewOwner(node, label, owner);
return subnode;
}
/**
* @dev Sets the resolver address for the specified node.
* @param node The node to update.
* @param resolver The address of the resolver.
*/
function setResolver(
bytes32 node,
address resolver
) public virtual override authorised(node) {
emit NewResolver(node, resolver);
records[node].resolver = resolver;
}
/**
* @dev Sets the TTL for the specified node.
* @param node The node to update.
* @param ttl The TTL in seconds.
*/
function setTTL(
bytes32 node,
uint64 ttl
) public virtual override authorised(node) {
emit NewTTL(node, ttl);
records[node].ttl = ttl;
}
/**
* @dev Enable or disable approval for a third party ("operator") to manage
* all of `msg.sender`'s ENS records. Emits the ApprovalForAll event.
* @param operator Address to add to the set of authorized operators.
* @param approved True if the operator is approved, false to revoke approval.
*/
function setApprovalForAll(
address operator,
bool approved
) external virtual override {
operators[msg.sender][operator] = approved;
emit ApprovalForAll(msg.sender, operator, approved);
}
/**
* @dev Returns the address that owns the specified node.
* @param node The specified node.
* @return address of the owner.
*/
function owner(
bytes32 node
) public view virtual override returns (address) {
address addr = records[node].owner;
if (addr == address(this)) {
return address(0x0);
}
return addr;
}
/**
* @dev Returns the address of the resolver for the specified node.
* @param node The specified node.
* @return address of the resolver.
*/
function resolver(
bytes32 node
) public view virtual override returns (address) {
return records[node].resolver;
}
/**
* @dev Returns the TTL of a node, and any records associated with it.
* @param node The specified node.
* @return ttl of the node.
*/
function ttl(bytes32 node) public view virtual override returns (uint64) {
return records[node].ttl;
}
/**
* @dev Returns whether a record has been imported to the registry.
* @param node The specified node.
* @return Bool if record exists
*/
function recordExists(
bytes32 node
) public view virtual override returns (bool) {
return records[node].owner != address(0x0);
}
/**
* @dev Query if an address is an authorized operator for another address.
* @param owner The address that owns the records.
* @param operator The address that acts on behalf of the owner.
* @return True if `operator` is an approved operator for `owner`, false otherwise.
*/
function isApprovedForAll(
address owner,
address operator
) external view virtual override 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);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.sol";
/**
* @dev Implementation of the {IERC20} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
* For a generic mechanism see {ERC20PresetMinterPauser}.
*
* TIP: For a detailed writeup see our guide
* https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* The default value of {decimals} is 18. To change this, you should override
* this function so it returns a different value.
*
* We have followed general OpenZeppelin Contracts guidelines: functions revert
* instead returning `false` on failure. This behavior is nonetheless
* conventional and does not conflict with the expectations of ERC20
* applications.
*
* Additionally, an {Approval} event is emitted on calls to {transferFrom}.
* This allows applications to reconstruct the allowance for all accounts just
* by listening to said events. Other implementations of the EIP may not emit
* these events, as it isn't required by the specification.
*
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
* functions have been added to mitigate the well-known issues around setting
* allowances. See {IERC20-approve}.
*/
contract ERC20 is Context, IERC20, IERC20Metadata {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/**
* @dev Sets the values for {name} and {symbol}.
*
* All two of these values are immutable: they can only be set once during
* construction.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5.05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the default value returned by this function, unless
* it's overridden.
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view virtual override returns (uint8) {
return 18;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - the caller must have a balance of at least `amount`.
*/
function transfer(address to, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_transfer(owner, to, amount);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
* `transferFrom`. This is semantically equivalent to an infinite approval.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address spender, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_approve(owner, spender, amount);
return true;
}
/**
* @dev See {IERC20-transferFrom}.
*
* Emits an {Approval} event indicating the updated allowance. This is not
* required by the EIP. See the note at the beginning of {ERC20}.
*
* NOTE: Does not update the allowance if the current allowance
* is the maximum `uint256`.
*
* Requirements:
*
* - `from` and `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
* - the caller must have allowance for ``from``'s tokens of at least
* `amount`.
*/
function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, amount);
_transfer(from, to, amount);
return true;
}
/**
* @dev Atomically increases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, allowance(owner, spender) + addedValue);
return true;
}
/**
* @dev Atomically decreases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `spender` must have allowance for the caller of at least
* `subtractedValue`.
*/
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
address owner = _msgSender();
uint256 currentAllowance = allowance(owner, spender);
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(owner, spender, currentAllowance - subtractedValue);
}
return true;
}
/**
* @dev Moves `amount` of tokens from `from` to `to`.
*
* This internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
*/
function _transfer(address from, address to, uint256 amount) internal virtual {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(from, to, amount);
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[from] = fromBalance - amount;
// Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by
// decrementing then incrementing.
_balances[to] += amount;
}
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
}
/** @dev Creates `amount` tokens and assigns them to `account`, increasing
* the total supply.
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
unchecked {
// Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.
_balances[account] += amount;
}
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
/**
* @dev Destroys `amount` tokens from `account`, reducing the
* total supply.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
*/
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
// Overflow not possible: amount <= accountBalance <= totalSupply.
_totalSupply -= amount;
}
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
/**
* @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*/
function _approve(address owner, address spender, uint256 amount) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
/**
* @dev Updates `owner` s allowance for `spender` based on spent `amount`.
*
* Does not update the allowance amount in case of infinite allowance.
* Revert if not enough allowance is available.
*
* Might emit an {Approval} event.
*/
function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(currentAllowance >= amount, "ERC20: insufficient allowance");
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
/**
* @dev Hook that is called before any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* will be transferred to `to`.
* - when `from` is zero, `amount` tokens will be minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}
/**
* @dev Hook that is called after any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* has been transferred to `to`.
* - when `from` is zero, `amount` tokens have been minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens have been burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}
}pragma solidity >=0.8.4;
import "@openzeppelin/contracts/access/Ownable.sol";
import "./profiles/ABIResolver.sol";
import "./profiles/AddrResolver.sol";
import "./profiles/ContentHashResolver.sol";
import "./profiles/DNSResolver.sol";
import "./profiles/InterfaceResolver.sol";
import "./profiles/NameResolver.sol";
import "./profiles/PubkeyResolver.sol";
import "./profiles/TextResolver.sol";
import "./profiles/ExtendedResolver.sol";
/**
* A simple resolver anyone can use; only allows the owner of a node to set its
* address.
*/
contract OwnedResolver is
Ownable,
ABIResolver,
AddrResolver,
ContentHashResolver,
DNSResolver,
InterfaceResolver,
NameResolver,
PubkeyResolver,
TextResolver,
ExtendedResolver
{
function isAuthorised(bytes32) internal view override returns (bool) {
return msg.sender == owner();
}
function supportsInterface(
bytes4 interfaceID
)
public
view
virtual
override(
ABIResolver,
AddrResolver,
ContentHashResolver,
DNSResolver,
InterfaceResolver,
NameResolver,
PubkeyResolver,
TextResolver
)
returns (bool)
{
return super.supportsInterface(interfaceID);
}
}pragma solidity >=0.8.4;
interface ENS {
// Logged when the owner of a node assigns a new owner to a subnode.
event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);
// Logged when the owner of a node transfers ownership to a new account.
event Transfer(bytes32 indexed node, address owner);
// Logged when the resolver for a node changes.
event NewResolver(bytes32 indexed node, address resolver);
// Logged when the TTL of a node changes
event NewTTL(bytes32 indexed node, uint64 ttl);
// Logged when an operator is added or removed.
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);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.4;
import "./IABIResolver.sol";
import "../ResolverBase.sol";
abstract contract ABIResolver is IABIResolver, ResolverBase {
mapping(uint64 => mapping(bytes32 => mapping(uint256 => bytes))) versionable_abis;
/**
* Sets the ABI associated with an ENS node.
* Nodes may have one ABI of each content type. To remove an ABI, set it to
* the empty string.
* @param node The node to update.
* @param contentType The content type of the ABI
* @param data The ABI data.
*/
function setABI(
bytes32 node,
uint256 contentType,
bytes calldata data
) external virtual authorised(node) {
// Content types must be powers of 2
require(((contentType - 1) & contentType) == 0);
versionable_abis[recordVersions[node]][node][contentType] = data;
emit ABIChanged(node, contentType);
}
/**
* Returns the ABI associated with an ENS node.
* Defined in EIP205.
* @param node The ENS node to query
* @param contentTypes A bitwise OR of the ABI formats accepted by the caller.
* @return contentType The content type of the return value
* @return data The ABI data
*/
function ABI(
bytes32 node,
uint256 contentTypes
) external view virtual override returns (uint256, bytes memory) {
mapping(uint256 => bytes) storage abiset = versionable_abis[
recordVersions[node]
][node];
for (
uint256 contentType = 1;
contentType <= contentTypes;
contentType <<= 1
) {
if (
(contentType & contentTypes) != 0 &&
abiset[contentType].length > 0
) {
return (contentType, abiset[contentType]);
}
}
return (0, bytes(""));
}
function supportsInterface(
bytes4 interfaceID
) public view virtual override returns (bool) {
return
interfaceID == type(IABIResolver).interfaceId ||
super.supportsInterface(interfaceID);
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.4;
import "../ResolverBase.sol";
import "./IAddrResolver.sol";
import "./IAddressResolver.sol";
abstract contract AddrResolver is
IAddrResolver,
IAddressResolver,
ResolverBase
{
uint256 private constant COIN_TYPE_ETH = 60;
mapping(uint64 => mapping(bytes32 => mapping(uint256 => bytes))) versionable_addresses;
/**
* Sets the address associated with an ENS node.
* May only be called by the owner of that node in the ENS registry.
* @param node The node to update.
* @param a The address to set.
*/
function setAddr(
bytes32 node,
address a
) external virtual authorised(node) {
setAddr(node, COIN_TYPE_ETH, addressToBytes(a));
}
/**
* Returns the address associated with an ENS node.
* @param node The ENS node to query.
* @return The associated address.
*/
function addr(
bytes32 node
) public view virtual override returns (address payable) {
bytes memory a = addr(node, COIN_TYPE_ETH);
if (a.length == 0) {
return payable(0);
}
return bytesToAddress(a);
}
function setAddr(
bytes32 node,
uint256 coinType,
bytes memory a
) public virtual authorised(node) {
emit AddressChanged(node, coinType, a);
if (coinType == COIN_TYPE_ETH) {
emit AddrChanged(node, bytesToAddress(a));
}
versionable_addresses[recordVersions[node]][node][coinType] = a;
}
function addr(
bytes32 node,
uint256 coinType
) public view virtual override returns (bytes memory) {
return versionable_addresses[recordVersions[node]][node][coinType];
}
function supportsInterface(
bytes4 interfaceID
) public view virtual override returns (bool) {
return
interfaceID == type(IAddrResolver).interfaceId ||
interfaceID == type(IAddressResolver).interfaceId ||
super.supportsInterface(interfaceID);
}
function bytesToAddress(
bytes memory b
) internal pure returns (address payable a) {
require(b.length == 20);
assembly {
a := div(mload(add(b, 32)), exp(256, 12))
}
}
function addressToBytes(address a) internal pure returns (bytes memory b) {
b = new bytes(20);
assembly {
mstore(add(b, 32), mul(a, exp(256, 12)))
}
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.4;
import "../ResolverBase.sol";
import "./IContentHashResolver.sol";
abstract contract ContentHashResolver is IContentHashResolver, ResolverBase {
mapping(uint64 => mapping(bytes32 => bytes)) versionable_hashes;
/**
* Sets the contenthash associated with an ENS node.
* May only be called by the owner of that node in the ENS registry.
* @param node The node to update.
* @param hash The contenthash to set
*/
function setContenthash(
bytes32 node,
bytes calldata hash
) external virtual authorised(node) {
versionable_hashes[recordVersions[node]][node] = hash;
emit ContenthashChanged(node, hash);
}
/**
* Returns the contenthash associated with an ENS node.
* @param node The ENS node to query.
* @return The associated contenthash.
*/
function contenthash(
bytes32 node
) external view virtual override returns (bytes memory) {
return versionable_hashes[recordVersions[node]][node];
}
function supportsInterface(
bytes4 interfaceID
) public view virtual override returns (bool) {
return
interfaceID == type(IContentHashResolver).interfaceId ||
super.supportsInterface(interfaceID);
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.4;
import "../ResolverBase.sol";
import "../../dnssec-oracle/RRUtils.sol";
import "./IDNSRecordResolver.sol";
import "./IDNSZoneResolver.sol";
abstract contract DNSResolver is
IDNSRecordResolver,
IDNSZoneResolver,
ResolverBase
{
using RRUtils for *;
using BytesUtils for bytes;
// Zone hashes for the domains.
// A zone hash is an EIP-1577 content hash in binary format that should point to a
// resource containing a single zonefile.
// node => contenthash
mapping(uint64 => mapping(bytes32 => bytes)) private versionable_zonehashes;
// The records themselves. Stored as binary RRSETs
// node => version => name => resource => data
mapping(uint64 => mapping(bytes32 => mapping(bytes32 => mapping(uint16 => bytes))))
private versionable_records;
// Count of number of entries for a given name. Required for DNS resolvers
// when resolving wildcards.
// node => version => name => number of records
mapping(uint64 => mapping(bytes32 => mapping(bytes32 => uint16)))
private versionable_nameEntriesCount;
/**
* Set one or more DNS records. Records are supplied in wire-format.
* Records with the same node/name/resource must be supplied one after the
* other to ensure the data is updated correctly. For example, if the data
* was supplied:
* a.example.com IN A 1.2.3.4
* a.example.com IN A 5.6.7.8
* www.example.com IN CNAME a.example.com.
* then this would store the two A records for a.example.com correctly as a
* single RRSET, however if the data was supplied:
* a.example.com IN A 1.2.3.4
* www.example.com IN CNAME a.example.com.
* a.example.com IN A 5.6.7.8
* then this would store the first A record, the CNAME, then the second A
* record which would overwrite the first.
*
* @param node the namehash of the node for which to set the records
* @param data the DNS wire format records to set
*/
function setDNSRecords(
bytes32 node,
bytes calldata data
) external virtual authorised(node) {
uint16 resource = 0;
uint256 offset = 0;
bytes memory name;
bytes memory value;
bytes32 nameHash;
uint64 version = recordVersions[node];
// Iterate over the data to add the resource records
for (
RRUtils.RRIterator memory iter = data.iterateRRs(0);
!iter.done();
iter.next()
) {
if (resource == 0) {
resource = iter.dnstype;
name = iter.name();
nameHash = keccak256(abi.encodePacked(name));
value = bytes(iter.rdata());
} else {
bytes memory newName = iter.name();
if (resource != iter.dnstype || !name.equals(newName)) {
setDNSRRSet(
node,
name,
resource,
data,
offset,
iter.offset - offset,
value.length == 0,
version
);
resource = iter.dnstype;
offset = iter.offset;
name = newName;
nameHash = keccak256(name);
value = bytes(iter.rdata());
}
}
}
if (name.length > 0) {
setDNSRRSet(
node,
name,
resource,
data,
offset,
data.length - offset,
value.length == 0,
version
);
}
}
/**
* Obtain a DNS record.
* @param node the namehash of the node for which to fetch the record
* @param name the keccak-256 hash of the fully-qualified name for which to fetch the record
* @param resource the ID of the resource as per https://en.wikipedia.org/wiki/List_of_DNS_record_types
* @return the DNS record in wire format if present, otherwise empty
*/
function dnsRecord(
bytes32 node,
bytes32 name,
uint16 resource
) public view virtual override returns (bytes memory) {
return versionable_records[recordVersions[node]][node][name][resource];
}
/**
* Check if a given node has records.
* @param node the namehash of the node for which to check the records
* @param name the namehash of the node for which to check the records
*/
function hasDNSRecords(
bytes32 node,
bytes32 name
) public view virtual returns (bool) {
return (versionable_nameEntriesCount[recordVersions[node]][node][
name
] != 0);
}
/**
* setZonehash sets the hash for the zone.
* May only be called by the owner of that node in the ENS registry.
* @param node The node to update.
* @param hash The zonehash to set
*/
function setZonehash(
bytes32 node,
bytes calldata hash
) external virtual authorised(node) {
uint64 currentRecordVersion = recordVersions[node];
bytes memory oldhash = versionable_zonehashes[currentRecordVersion][
node
];
versionable_zonehashes[currentRecordVersion][node] = hash;
emit DNSZonehashChanged(node, oldhash, hash);
}
/**
* zonehash obtains the hash for the zone.
* @param node The ENS node to query.
* @return The associated contenthash.
*/
function zonehash(
bytes32 node
) external view virtual override returns (bytes memory) {
return versionable_zonehashes[recordVersions[node]][node];
}
function supportsInterface(
bytes4 interfaceID
) public view virtual override returns (bool) {
return
interfaceID == type(IDNSRecordResolver).interfaceId ||
interfaceID == type(IDNSZoneResolver).interfaceId ||
super.supportsInterface(interfaceID);
}
function setDNSRRSet(
bytes32 node,
bytes memory name,
uint16 resource,
bytes memory data,
uint256 offset,
uint256 size,
bool deleteRecord,
uint64 version
) private {
bytes32 nameHash = keccak256(name);
bytes memory rrData = data.substring(offset, size);
if (deleteRecord) {
if (
versionable_records[version][node][nameHash][resource].length !=
0
) {
versionable_nameEntriesCount[version][node][nameHash]--;
}
delete (versionable_records[version][node][nameHash][resource]);
emit DNSRecordDeleted(node, name, resource);
} else {
if (
versionable_records[version][node][nameHash][resource].length ==
0
) {
versionable_nameEntriesCount[version][node][nameHash]++;
}
versionable_records[version][node][nameHash][resource] = rrData;
emit DNSRecordChanged(node, name, resource, rrData);
}
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.4;
import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import "../ResolverBase.sol";
import "./AddrResolver.sol";
import "./IInterfaceResolver.sol";
abstract contract InterfaceResolver is IInterfaceResolver, AddrResolver {
mapping(uint64 => mapping(bytes32 => mapping(bytes4 => address))) versionable_interfaces;
/**
* Sets an interface associated with a name.
* Setting the address to 0 restores the default behaviour of querying the contract at `addr()` for interface support.
* @param node The node to update.
* @param interfaceID The EIP 165 interface ID.
* @param implementer The address of a contract that implements this interface for this node.
*/
function setInterface(
bytes32 node,
bytes4 interfaceID,
address implementer
) external virtual authorised(node) {
versionable_interfaces[recordVersions[node]][node][
interfaceID
] = implementer;
emit InterfaceChanged(node, interfaceID, implementer);
}
/**
* Returns the address of a contract that implements the specified interface for this name.
* If an implementer has not been set for this interfaceID and name, the resolver will query
* the contract at `addr()`. If `addr()` is set, a contract exists at that address, and that
* contract implements EIP165 and returns `true` for the specified interfaceID, its address
* will be returned.
* @param node The ENS node to query.
* @param interfaceID The EIP 165 interface ID to check for.
* @return The address that implements this interface, or 0 if the interface is unsupported.
*/
function interfaceImplementer(
bytes32 node,
bytes4 interfaceID
) external view virtual override returns (address) {
address implementer = versionable_interfaces[recordVersions[node]][
node
][interfaceID];
if (implementer != address(0)) {
return implementer;
}
address a = addr(node);
if (a == address(0)) {
return address(0);
}
(bool success, bytes memory returnData) = a.staticcall(
abi.encodeWithSignature(
"supportsInterface(bytes4)",
type(IERC165).interfaceId
)
);
if (!success || returnData.length < 32 || returnData[31] == 0) {
// EIP 165 not supported by target
return address(0);
}
(success, returnData) = a.staticcall(
abi.encodeWithSignature("supportsInterface(bytes4)", interfaceID)
);
if (!success || returnData.length < 32 || returnData[31] == 0) {
// Specified interface not supported by target
return address(0);
}
return a;
}
function supportsInterface(
bytes4 interfaceID
) public view virtual override returns (bool) {
return
interfaceID == type(IInterfaceResolver).interfaceId ||
super.supportsInterface(interfaceID);
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.4;
import "../ResolverBase.sol";
import "./INameResolver.sol";
abstract contract NameResolver is INameResolver, ResolverBase {
mapping(uint64 => mapping(bytes32 => string)) versionable_names;
/**
* Sets the name associated with an ENS node, for reverse records.
* May only be called by the owner of that node in the ENS registry.
* @param node The node to update.
*/
function setName(
bytes32 node,
string calldata newName
) external virtual authorised(node) {
versionable_names[recordVersions[node]][node] = newName;
emit NameChanged(node, newName);
}
/**
* Returns the name associated with an ENS node, for reverse records.
* Defined in EIP181.
* @param node The ENS node to query.
* @return The associated name.
*/
function name(
bytes32 node
) external view virtual override returns (string memory) {
return versionable_names[recordVersions[node]][node];
}
function supportsInterface(
bytes4 interfaceID
) public view virtual override returns (bool) {
return
interfaceID == type(INameResolver).interfaceId ||
super.supportsInterface(interfaceID);
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.4;
import "../ResolverBase.sol";
import "./IPubkeyResolver.sol";
abstract contract PubkeyResolver is IPubkeyResolver, ResolverBase {
struct PublicKey {
bytes32 x;
bytes32 y;
}
mapping(uint64 => mapping(bytes32 => PublicKey)) versionable_pubkeys;
/**
* Sets the SECP256k1 public key associated with an ENS node.
* @param node The ENS node to query
* @param x the X coordinate of the curve point for the public key.
* @param y the Y coordinate of the curve point for the public key.
*/
function setPubkey(
bytes32 node,
bytes32 x,
bytes32 y
) external virtual authorised(node) {
versionable_pubkeys[recordVersions[node]][node] = PublicKey(x, y);
emit PubkeyChanged(node, x, y);
}
/**
* Returns the SECP256k1 public key associated with an ENS node.
* Defined in EIP 619.
* @param node The ENS node to query
* @return x The X coordinate of the curve point for the public key.
* @return y The Y coordinate of the curve point for the public key.
*/
function pubkey(
bytes32 node
) external view virtual override returns (bytes32 x, bytes32 y) {
uint64 currentRecordVersion = recordVersions[node];
return (
versionable_pubkeys[currentRecordVersion][node].x,
versionable_pubkeys[currentRecordVersion][node].y
);
}
function supportsInterface(
bytes4 interfaceID
) public view virtual override returns (bool) {
return
interfaceID == type(IPubkeyResolver).interfaceId ||
super.supportsInterface(interfaceID);
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.4;
import "../ResolverBase.sol";
import "./ITextResolver.sol";
abstract contract TextResolver is ITextResolver, ResolverBase {
mapping(uint64 => mapping(bytes32 => mapping(string => string))) versionable_texts;
/**
* Sets the text data associated with an ENS node and key.
* May only be called by the owner of that node in the ENS registry.
* @param node The node to update.
* @param key The key to set.
* @param value The text data value to set.
*/
function setText(
bytes32 node,
string calldata key,
string calldata value
) external virtual authorised(node) {
versionable_texts[recordVersions[node]][node][key] = value;
emit TextChanged(node, key, key, value);
}
/**
* Returns the text data associated with an ENS node and key.
* @param node The ENS node to query.
* @param key The text data key to query.
* @return The associated text data.
*/
function text(
bytes32 node,
string calldata key
) external view virtual override returns (string memory) {
return versionable_texts[recordVersions[node]][node][key];
}
function supportsInterface(
bytes4 interfaceID
) public view virtual override returns (bool) {
return
interfaceID == type(ITextResolver).interfaceId ||
super.supportsInterface(interfaceID);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
contract ExtendedResolver {
function resolve(
bytes memory /* name */,
bytes memory data
) external view returns (bytes memory) {
(bool success, bytes memory result) = address(this).staticcall(data);
if (success) {
return result;
} else {
// Revert with the reason provided by the call
assembly {
revert(add(result, 0x20), mload(result))
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.4;
interface IABIResolver {
event ABIChanged(bytes32 indexed node, uint256 indexed contentType);
/**
* Returns the ABI associated with an ENS node.
* Defined in EIP205.
* @param node The ENS node to query
* @param contentTypes A bitwise OR of the ABI formats accepted by the caller.
* @return contentType The content type of the return value
* @return data The ABI data
*/
function ABI(
bytes32 node,
uint256 contentTypes
) external view returns (uint256, bytes memory);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.4;
import "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import "./profiles/IVersionableResolver.sol";
abstract contract ResolverBase is ERC165, IVersionableResolver {
mapping(bytes32 => uint64) public recordVersions;
function isAuthorised(bytes32 node) internal view virtual returns (bool);
modifier authorised(bytes32 node) {
require(isAuthorised(node));
_;
}
/**
* Increments the record version associated with an ENS node.
* May only be called by the owner of that node in the ENS registry.
* @param node The node to update.
*/
function clearRecords(bytes32 node) public virtual authorised(node) {
recordVersions[node]++;
emit VersionChanged(node, recordVersions[node]);
}
function supportsInterface(
bytes4 interfaceID
) public view virtual override returns (bool) {
return
interfaceID == type(IVersionableResolver).interfaceId ||
super.supportsInterface(interfaceID);
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.4;
/**
* Interface for the legacy (ETH-only) addr function.
*/
interface IAddrResolver {
event AddrChanged(bytes32 indexed node, address a);
/**
* Returns the address associated with an ENS node.
* @param node The ENS node to query.
* @return The associated address.
*/
function addr(bytes32 node) external view returns (address payable);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.4;
/**
* Interface for the new (multicoin) addr function.
*/
interface IAddressResolver {
event AddressChanged(
bytes32 indexed node,
uint256 coinType,
bytes newAddress
);
function addr(
bytes32 node,
uint256 coinType
) external view returns (bytes memory);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.4;
interface IContentHashResolver {
event ContenthashChanged(bytes32 indexed node, bytes hash);
/**
* Returns the contenthash associated with an ENS node.
* @param node The ENS node to query.
* @return The associated contenthash.
*/
function contenthash(bytes32 node) external view returns (bytes memory);
}pragma solidity ^0.8.4;
import "./BytesUtils.sol";
import "@ensdomains/buffer/contracts/Buffer.sol";
/**
* @dev RRUtils is a library that provides utilities for parsing DNS resource records.
*/
library RRUtils {
using BytesUtils for *;
using Buffer for *;
/**
* @dev Returns the number of bytes in the DNS name at 'offset' in 'self'.
* @param self The byte array to read a name from.
* @param offset The offset to start reading at.
* @return The length of the DNS name at 'offset', in bytes.
*/
function nameLength(
bytes memory self,
uint256 offset
) internal pure returns (uint256) {
uint256 idx = offset;
while (true) {
assert(idx < self.length);
uint256 labelLen = self.readUint8(idx);
idx += labelLen + 1;
if (labelLen == 0) {
break;
}
}
return idx - offset;
}
/**
* @dev Returns a DNS format name at the specified offset of self.
* @param self The byte array to read a name from.
* @param offset The offset to start reading at.
* @return ret The name.
*/
function readName(
bytes memory self,
uint256 offset
) internal pure returns (bytes memory ret) {
uint256 len = nameLength(self, offset);
return self.substring(offset, len);
}
/**
* @dev Returns the number of labels in the DNS name at 'offset' in 'self'.
* @param self The byte array to read a name from.
* @param offset The offset to start reading at.
* @return The number of labels in the DNS name at 'offset', in bytes.
*/
function labelCount(
bytes memory self,
uint256 offset
) internal pure returns (uint256) {
uint256 count = 0;
while (true) {
assert(offset < self.length);
uint256 labelLen = self.readUint8(offset);
offset += labelLen + 1;
if (labelLen == 0) {
break;
}
count += 1;
}
return count;
}
uint256 constant RRSIG_TYPE = 0;
uint256 constant RRSIG_ALGORITHM = 2;
uint256 constant RRSIG_LABELS = 3;
uint256 constant RRSIG_TTL = 4;
uint256 constant RRSIG_EXPIRATION = 8;
uint256 constant RRSIG_INCEPTION = 12;
uint256 constant RRSIG_KEY_TAG = 16;
uint256 constant RRSIG_SIGNER_NAME = 18;
struct SignedSet {
uint16 typeCovered;
uint8 algorithm;
uint8 labels;
uint32 ttl;
uint32 expiration;
uint32 inception;
uint16 keytag;
bytes signerName;
bytes data;
bytes name;
}
function readSignedSet(
bytes memory data
) internal pure returns (SignedSet memory self) {
self.typeCovered = data.readUint16(RRSIG_TYPE);
self.algorithm = data.readUint8(RRSIG_ALGORITHM);
self.labels = data.readUint8(RRSIG_LABELS);
self.ttl = data.readUint32(RRSIG_TTL);
self.expiration = data.readUint32(RRSIG_EXPIRATION);
self.inception = data.readUint32(RRSIG_INCEPTION);
self.keytag = data.readUint16(RRSIG_KEY_TAG);
self.signerName = readName(data, RRSIG_SIGNER_NAME);
self.data = data.substring(
RRSIG_SIGNER_NAME + self.signerName.length,
data.length - RRSIG_SIGNER_NAME - self.signerName.length
);
}
function rrs(
SignedSet memory rrset
) internal pure returns (RRIterator memory) {
return iterateRRs(rrset.data, 0);
}
/**
* @dev An iterator over resource records.
*/
struct RRIterator {
bytes data;
uint256 offset;
uint16 dnstype;
uint16 class;
uint32 ttl;
uint256 rdataOffset;
uint256 nextOffset;
}
/**
* @dev Begins iterating over resource records.
* @param self The byte string to read from.
* @param offset The offset to start reading at.
* @return ret An iterator object.
*/
function iterateRRs(
bytes memory self,
uint256 offset
) internal pure returns (RRIterator memory ret) {
ret.data = self;
ret.nextOffset = offset;
next(ret);
}
/**
* @dev Returns true iff there are more RRs to iterate.
* @param iter The iterator to check.
* @return True iff the iterator has finished.
*/
function done(RRIterator memory iter) internal pure returns (bool) {
return iter.offset >= iter.data.length;
}
/**
* @dev Moves the iterator to the next resource record.
* @param iter The iterator to advance.
*/
function next(RRIterator memory iter) internal pure {
iter.offset = iter.nextOffset;
if (iter.offset >= iter.data.length) {
return;
}
// Skip the name
uint256 off = iter.offset + nameLength(iter.data, iter.offset);
// Read type, class, and ttl
iter.dnstype = iter.data.readUint16(off);
off += 2;
iter.class = iter.data.readUint16(off);
off += 2;
iter.ttl = iter.data.readUint32(off);
off += 4;
// Read the rdata
uint256 rdataLength = iter.data.readUint16(off);
off += 2;
iter.rdataOffset = off;
iter.nextOffset = off + rdataLength;
}
/**
* @dev Returns the name of the current record.
* @param iter The iterator.
* @return A new bytes object containing the owner name from the RR.
*/
function name(RRIterator memory iter) internal pure returns (bytes memory) {
return
iter.data.substring(
iter.offset,
nameLength(iter.data, iter.offset)
);
}
/**
* @dev Returns the rdata portion of the current record.
* @param iter The iterator.
* @return A new bytes object containing the RR's RDATA.
*/
function rdata(
RRIterator memory iter
) internal pure returns (bytes memory) {
return
iter.data.substring(
iter.rdataOffset,
iter.nextOffset - iter.rdataOffset
);
}
uint256 constant DNSKEY_FLAGS = 0;
uint256 constant DNSKEY_PROTOCOL = 2;
uint256 constant DNSKEY_ALGORITHM = 3;
uint256 constant DNSKEY_PUBKEY = 4;
struct DNSKEY {
uint16 flags;
uint8 protocol;
uint8 algorithm;
bytes publicKey;
}
function readDNSKEY(
bytes memory data,
uint256 offset,
uint256 length
) internal pure returns (DNSKEY memory self) {
self.flags = data.readUint16(offset + DNSKEY_FLAGS);
self.protocol = data.readUint8(offset + DNSKEY_PROTOCOL);
self.algorithm = data.readUint8(offset + DNSKEY_ALGORITHM);
self.publicKey = data.substring(
offset + DNSKEY_PUBKEY,
length - DNSKEY_PUBKEY
);
}
uint256 constant DS_KEY_TAG = 0;
uint256 constant DS_ALGORITHM = 2;
uint256 constant DS_DIGEST_TYPE = 3;
uint256 constant DS_DIGEST = 4;
struct DS {
uint16 keytag;
uint8 algorithm;
uint8 digestType;
bytes digest;
}
function readDS(
bytes memory data,
uint256 offset,
uint256 length
) internal pure returns (DS memory self) {
self.keytag = data.readUint16(offset + DS_KEY_TAG);
self.algorithm = data.readUint8(offset + DS_ALGORITHM);
self.digestType = data.readUint8(offset + DS_DIGEST_TYPE);
self.digest = data.substring(offset + DS_DIGEST, length - DS_DIGEST);
}
function isSubdomainOf(
bytes memory self,
bytes memory other
) internal pure returns (bool) {
uint256 off = 0;
uint256 counts = labelCount(self, 0);
uint256 othercounts = labelCount(other, 0);
while (counts > othercounts) {
off = progress(self, off);
counts--;
}
return self.equals(off, other, 0);
}
function compareNames(
bytes memory self,
bytes memory other
) internal pure returns (int256) {
if (self.equals(other)) {
return 0;
}
uint256 off;
uint256 otheroff;
uint256 prevoff;
uint256 otherprevoff;
uint256 counts = labelCount(self, 0);
uint256 othercounts = labelCount(other, 0);
// Keep removing labels from the front of the name until both names are equal length
while (counts > othercounts) {
prevoff = off;
off = progress(self, off);
counts--;
}
while (othercounts > counts) {
otherprevoff = otheroff;
otheroff = progress(other, otheroff);
othercounts--;
}
// Compare the last nonequal labels to each other
while (counts > 0 && !self.equals(off, other, otheroff)) {
prevoff = off;
off = progress(self, off);
otherprevoff = otheroff;
otheroff = progress(other, otheroff);
counts -= 1;
}
if (off == 0) {
return -1;
}
if (otheroff == 0) {
return 1;
}
return
self.compare(
prevoff + 1,
self.readUint8(prevoff),
other,
otherprevoff + 1,
other.readUint8(otherprevoff)
);
}
/**
* @dev Compares two serial numbers using RFC1982 serial number math.
*/
function serialNumberGte(
uint32 i1,
uint32 i2
) internal pure returns (bool) {
unchecked {
return int32(i1) - int32(i2) >= 0;
}
}
function progress(
bytes memory body,
uint256 off
) internal pure returns (uint256) {
return off + 1 + body.readUint8(off);
}
/**
* @dev Computes the keytag for a chunk of data.
* @param data The data to compute a keytag for.
* @return The computed key tag.
*/
function computeKeytag(bytes memory data) internal pure returns (uint16) {
/* This function probably deserves some explanation.
* The DNSSEC keytag function is a checksum that relies on summing up individual bytes
* from the input string, with some mild bitshifting. Here's a Naive solidity implementation:
*
* function computeKeytag(bytes memory data) internal pure returns (uint16) {
* uint ac;
* for (uint i = 0; i < data.length; i++) {
* ac += i & 1 == 0 ? uint16(data.readUint8(i)) << 8 : data.readUint8(i);
* }
* return uint16(ac + (ac >> 16));
* }
*
* The EVM, with its 256 bit words, is exceedingly inefficient at doing byte-by-byte operations;
* the code above, on reasonable length inputs, consumes over 100k gas. But we can make the EVM's
* large words work in our favour.
*
* The code below works by treating the input as a series of 256 bit words. It first masks out
* even and odd bytes from each input word, adding them to two separate accumulators `ac1` and `ac2`.
* The bytes are separated by empty bytes, so as long as no individual sum exceeds 2^16-1, we're
* effectively summing 16 different numbers with each EVM ADD opcode.
*
* Once it's added up all the inputs, it has to add all the 16 bit values in `ac1` and `ac2` together.
* It does this using the same trick - mask out every other value, shift to align them, add them together.
* After the first addition on both accumulators, there's enough room to add the two accumulators together,
* and the remaining sums can be done just on ac1.
*/
unchecked {
require(data.length <= 8192, "Long keys not permitted");
uint256 ac1;
uint256 ac2;
for (uint256 i = 0; i < data.length + 31; i += 32) {
uint256 word;
assembly {
word := mload(add(add(data, 32), i))
}
if (i + 32 > data.length) {
uint256 unused = 256 - (data.length - i) * 8;
word = (word >> unused) << unused;
}
ac1 +=
(word &
0xFF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00) >>
8;
ac2 += (word &
0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF);
}
ac1 =
(ac1 &
0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) +
((ac1 &
0xFFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000) >>
16);
ac2 =
(ac2 &
0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) +
((ac2 &
0xFFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000) >>
16);
ac1 = (ac1 << 8) + ac2;
ac1 =
(ac1 &
0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) +
((ac1 &
0xFFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000) >>
32);
ac1 =
(ac1 &
0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) +
((ac1 &
0xFFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF0000000000000000) >>
64);
ac1 =
(ac1 &
0x00000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) +
(ac1 >> 128);
ac1 += (ac1 >> 16) & 0xFFFF;
return uint16(ac1);
}
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.4;
interface IDNSRecordResolver {
// DNSRecordChanged is emitted whenever a given node/name/resource's RRSET is updated.
event DNSRecordChanged(
bytes32 indexed node,
bytes name,
uint16 resource,
bytes record
);
// DNSRecordDeleted is emitted whenever a given node/name/resource's RRSET is deleted.
event DNSRecordDeleted(bytes32 indexed node, bytes name, uint16 resource);
/**
* Obtain a DNS record.
* @param node the namehash of the node for which to fetch the record
* @param name the keccak-256 hash of the fully-qualified name for which to fetch the record
* @param resource the ID of the resource as per https://en.wikipedia.org/wiki/List_of_DNS_record_types
* @return the DNS record in wire format if present, otherwise empty
*/
function dnsRecord(
bytes32 node,
bytes32 name,
uint16 resource
) external view returns (bytes memory);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.4;
interface IDNSZoneResolver {
// DNSZonehashChanged is emitted whenever a given node's zone hash is updated.
event DNSZonehashChanged(
bytes32 indexed node,
bytes lastzonehash,
bytes zonehash
);
/**
* zonehash obtains the hash for the zone.
* @param node The ENS node to query.
* @return The associated contenthash.
*/
function zonehash(bytes32 node) external view returns (bytes memory);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.4;
interface IInterfaceResolver {
event InterfaceChanged(
bytes32 indexed node,
bytes4 indexed interfaceID,
address implementer
);
/**
* Returns the address of a contract that implements the specified interface for this name.
* If an implementer has not been set for this interfaceID and name, the resolver will query
* the contract at `addr()`. If `addr()` is set, a contract exists at that address, and that
* contract implements EIP165 and returns `true` for the specified interfaceID, its address
* will be returned.
* @param node The ENS node to query.
* @param interfaceID The EIP 165 interface ID to check for.
* @return The address that implements this interface, or 0 if the interface is unsupported.
*/
function interfaceImplementer(
bytes32 node,
bytes4 interfaceID
) external view returns (address);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.4;
interface INameResolver {
event NameChanged(bytes32 indexed node, string name);
/**
* Returns the name associated with an ENS node, for reverse records.
* Defined in EIP181.
* @param node The ENS node to query.
* @return The associated name.
*/
function name(bytes32 node) external view returns (string memory);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.4;
interface IPubkeyResolver {
event PubkeyChanged(bytes32 indexed node, bytes32 x, bytes32 y);
/**
* Returns the SECP256k1 public key associated with an ENS node.
* Defined in EIP 619.
* @param node The ENS node to query
* @return x The X coordinate of the curve point for the public key.
* @return y The Y coordinate of the curve point for the public key.
*/
function pubkey(bytes32 node) external view returns (bytes32 x, bytes32 y);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.4;
interface ITextResolver {
event TextChanged(
bytes32 indexed node,
string indexed indexedKey,
string key,
string value
);
/**
* Returns the text data associated with an ENS node and key.
* @param node The ENS node to query.
* @param key The text data key to query.
* @return The associated text data.
*/
function text(
bytes32 node,
string calldata key
) external view returns (string memory);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
pragma solidity ^0.8.0;
import "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.4;
interface IVersionableResolver {
event VersionChanged(bytes32 indexed node, uint64 newVersion);
function recordVersions(bytes32 node) external view returns (uint64);
}pragma solidity ^0.8.4;
library BytesUtils {
error OffsetOutOfBoundsError(uint256 offset, uint256 length);
/*
* @dev Returns the keccak-256 hash of a byte range.
* @param self The byte string to hash.
* @param offset The position to start hashing at.
* @param len The number of bytes to hash.
* @return The hash of the byte range.
*/
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)
}
}
/*
* @dev Returns a positive number if `other` comes lexicographically after
* `self`, a negative number if it comes before, or zero if the
* contents of the two bytes are equal.
* @param self The first bytes to compare.
* @param other The second bytes to compare.
* @return The result of the comparison.
*/
function compare(
bytes memory self,
bytes memory other
) internal pure returns (int256) {
return compare(self, 0, self.length, other, 0, other.length);
}
/*
* @dev Returns a positive number if `other` comes lexicographically after
* `self`, a negative number if it comes before, or zero if the
* contents of the two bytes are equal. Comparison is done per-rune,
* on unicode codepoints.
* @param self The first bytes to compare.
* @param offset The offset of self.
* @param len The length of self.
* @param other The second bytes to compare.
* @param otheroffset The offset of the other string.
* @param otherlen The length of the other string.
* @return The result of the comparison.
*/
function compare(
bytes memory self,
uint256 offset,
uint256 len,
bytes memory other,
uint256 otheroffset,
uint256 otherlen
) internal pure returns (int256) {
if (offset + len > self.length) {
revert OffsetOutOfBoundsError(offset + len, self.length);
}
if (otheroffset + otherlen > other.length) {
revert OffsetOutOfBoundsError(otheroffset + otherlen, other.length);
}
uint256 shortest = len;
if (otherlen < len) shortest = otherlen;
uint256 selfptr;
uint256 otherptr;
assembly {
selfptr := add(self, add(offset, 32))
otherptr := add(other, add(otheroffset, 32))
}
for (uint256 idx = 0; idx < shortest; idx += 32) {
uint256 a;
uint256 b;
assembly {
a := mload(selfptr)
b := mload(otherptr)
}
if (a != b) {
// Mask out irrelevant bytes and check again
uint256 mask;
if (shortest - idx >= 32) {
mask = type(uint256).max;
} else {
mask = ~(2 ** (8 * (idx + 32 - shortest)) - 1);
}
int256 diff = int256(a & mask) - int256(b & mask);
if (diff != 0) return diff;
}
selfptr += 32;
otherptr += 32;
}
return int256(len) - int256(otherlen);
}
/*
* @dev Returns true if the two byte ranges are equal.
* @param self The first byte range to compare.
* @param offset The offset into the first byte range.
* @param other The second byte range to compare.
* @param otherOffset The offset into the second byte range.
* @param len The number of bytes to compare
* @return True if the byte ranges are equal, false otherwise.
*/
function equals(
bytes memory self,
uint256 offset,
bytes memory other,
uint256 otherOffset,
uint256 len
) internal pure returns (bool) {
return keccak(self, offset, len) == keccak(other, otherOffset, len);
}
/*
* @dev Returns true if the two byte ranges are equal with offsets.
* @param self The first byte range to compare.
* @param offset The offset into the first byte range.
* @param other The second byte range to compare.
* @param otherOffset The offset into the second byte range.
* @return True if the byte ranges are equal, false otherwise.
*/
function equals(
bytes memory self,
uint256 offset,
bytes memory other,
uint256 otherOffset
) internal pure returns (bool) {
return
keccak(self, offset, self.length - offset) ==
keccak(other, otherOffset, other.length - otherOffset);
}
/*
* @dev Compares a range of 'self' to all of 'other' and returns True iff
* they are equal.
* @param self The first byte range to compare.
* @param offset The offset into the first byte range.
* @param other The second byte range to compare.
* @return True if the byte ranges are equal, false otherwise.
*/
function equals(
bytes memory self,
uint256 offset,
bytes memory other
) internal pure returns (bool) {
return
self.length == offset + other.length &&
equals(self, offset, other, 0, other.length);
}
/*
* @dev Returns true if the two byte ranges are equal.
* @param self The first byte range to compare.
* @param other The second byte range to compare.
* @return True if the byte ranges are equal, false otherwise.
*/
function equals(
bytes memory self,
bytes memory other
) internal pure returns (bool) {
return
self.length == other.length &&
equals(self, 0, other, 0, self.length);
}
/*
* @dev Returns the 8-bit number at the specified index of self.
* @param self The byte string.
* @param idx The index into the bytes
* @return The specified 8 bits of the string, interpreted as an integer.
*/
function readUint8(
bytes memory self,
uint256 idx
) internal pure returns (uint8 ret) {
return uint8(self[idx]);
}
/*
* @dev Returns the 16-bit number at the specified index of self.
* @param self The byte string.
* @param idx The index into the bytes
* @return The specified 16 bits of the string, interpreted as an integer.
*/
function readUint16(
bytes memory self,
uint256 idx
) internal pure returns (uint16 ret) {
require(idx + 2 <= self.length);
assembly {
ret := and(mload(add(add(self, 2), idx)), 0xFFFF)
}
}
/*
* @dev Returns the 32-bit number at the specified index of self.
* @param self The byte string.
* @param idx The index into the bytes
* @return The specified 32 bits of the string, interpreted as an integer.
*/
function readUint32(
bytes memory self,
uint256 idx
) internal pure returns (uint32 ret) {
require(idx + 4 <= self.length);
assembly {
ret := and(mload(add(add(self, 4), idx)), 0xFFFFFFFF)
}
}
/*
* @dev Returns the 32 byte value at the specified index of self.
* @param self The byte string.
* @param idx The index into the bytes
* @return The specified 32 bytes of the string.
*/
function readBytes32(
bytes memory self,
uint256 idx
) internal pure returns (bytes32 ret) {
require(idx + 32 <= self.length);
assembly {
ret := mload(add(add(self, 32), idx))
}
}
/*
* @dev Returns the 32 byte value at the specified index of self.
* @param self The byte string.
* @param idx The index into the bytes
* @return The specified 32 bytes of the string.
*/
function readBytes20(
bytes memory self,
uint256 idx
) internal pure returns (bytes20 ret) {
require(idx + 20 <= self.length);
assembly {
ret := and(
mload(add(add(self, 32), idx)),
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000
)
}
}
/*
* @dev Returns the n byte value at the specified index of self.
* @param self The byte string.
* @param idx The index into the bytes.
* @param len The number of bytes.
* @return The specified 32 bytes of the string.
*/
function readBytesN(
bytes memory self,
uint256 idx,
uint256 len
) internal pure returns (bytes32 ret) {
require(len <= 32);
require(idx + len <= self.length);
assembly {
let mask := not(sub(exp(256, sub(32, len)), 1))
ret := and(mload(add(add(self, 32), idx)), mask)
}
}
function memcpy(uint256 dest, uint256 src, uint256 len) private pure {
// Copy word-length chunks while possible
for (; len >= 32; len -= 32) {
assembly {
mstore(dest, mload(src))
}
dest += 32;
src += 32;
}
// Copy remaining bytes
unchecked {
uint256 mask = (256 ** (32 - len)) - 1;
assembly {
let srcpart := and(mload(src), not(mask))
let destpart := and(mload(dest), mask)
mstore(dest, or(destpart, srcpart))
}
}
}
/*
* @dev Copies a substring into a new byte string.
* @param self The byte string to copy from.
* @param offset The offset to start copying at.
* @param len The number of bytes to copy.
*/
function substring(
bytes memory self,
uint256 offset,
uint256 len
) internal pure returns (bytes memory) {
require(offset + len <= self.length);
bytes memory ret = new bytes(len);
uint256 dest;
uint256 src;
assembly {
dest := add(ret, 32)
src := add(add(self, 32), offset)
}
memcpy(dest, src, len);
return ret;
}
// Maps characters from 0x30 to 0x7A to their base32 values.
// 0xFF represents invalid characters in that range.
bytes constant base32HexTable =
hex"00010203040506070809FFFFFFFFFFFFFF0A0B0C0D0E0F101112131415161718191A1B1C1D1E1FFFFFFFFFFFFFFFFFFFFF0A0B0C0D0E0F101112131415161718191A1B1C1D1E1F";
/**
* @dev Decodes unpadded base32 data of up to one word in length.
* @param self The data to decode.
* @param off Offset into the string to start at.
* @param len Number of characters to decode.
* @return The decoded data, left aligned.
*/
function base32HexDecodeWord(
bytes memory self,
uint256 off,
uint256 len
) internal pure returns (bytes32) {
require(len <= 52);
uint256 ret = 0;
uint8 decoded;
for (uint256 i = 0; i < len; i++) {
bytes1 char = self[off + i];
require(char >= 0x30 && char <= 0x7A);
decoded = uint8(base32HexTable[uint256(uint8(char)) - 0x30]);
require(decoded <= 0x20);
if (i == len - 1) {
break;
}
ret = (ret << 5) | decoded;
}
uint256 bitlen = len * 5;
if (len % 8 == 0) {
// Multiple of 8 characters, no padding
ret = (ret << 5) | decoded;
} else if (len % 8 == 2) {
// Two extra characters - 1 byte
ret = (ret << 3) | (decoded >> 2);
bitlen -= 2;
} else if (len % 8 == 4) {
// Four extra characters - 2 bytes
ret = (ret << 1) | (decoded >> 4);
bitlen -= 4;
} else if (len % 8 == 5) {
// Five extra characters - 3 bytes
ret = (ret << 4) | (decoded >> 1);
bitlen -= 1;
} else if (len % 8 == 7) {
// Seven extra characters - 4 bytes
ret = (ret << 2) | (decoded >> 3);
bitlen -= 3;
} else {
revert();
}
return bytes32(ret << (256 - bitlen));
}
/**
* @dev Finds the first occurrence of the byte `needle` in `self`.
* @param self The string to search
* @param off The offset to start searching at
* @param len The number of bytes to search
* @param needle The byte to search for
* @return The offset of `needle` in `self`, or 2**256-1 if it was not found.
*/
function find(
bytes memory self,
uint256 off,
uint256 len,
bytes1 needle
) internal pure returns (uint256) {
for (uint256 idx = off; idx < off + len; idx++) {
if (self[idx] == needle) {
return idx;
}
}
return type(uint256).max;
}
}// SPDX-License-Identifier: BSD-2-Clause
pragma solidity ^0.8.4;
/**
* @dev A library for working with mutable byte buffers in Solidity.
*
* Byte buffers are mutable and expandable, and provide a variety of primitives
* for appending to them. At any time you can fetch a bytes object containing the
* current contents of the buffer. The bytes object should not be stored between
* operations, as it may change due to resizing of the buffer.
*/
library Buffer {
/**
* @dev Represents a mutable buffer. Buffers have a current value (buf) and
* a capacity. The capacity may be longer than the current value, in
* which case it can be extended without the need to allocate more memory.
*/
struct buffer {
bytes buf;
uint capacity;
}
/**
* @dev Initializes a buffer with an initial capacity.
* @param buf The buffer to initialize.
* @param capacity The number of bytes of space to allocate the buffer.
* @return The buffer, for chaining.
*/
function init(buffer memory buf, uint capacity) internal pure returns(buffer memory) {
if (capacity % 32 != 0) {
capacity += 32 - (capacity % 32);
}
// Allocate space for the buffer data
buf.capacity = capacity;
assembly {
let ptr := mload(0x40)
mstore(buf, ptr)
mstore(ptr, 0)
let fpm := add(32, add(ptr, capacity))
if lt(fpm, ptr) {
revert(0, 0)
}
mstore(0x40, fpm)
}
return buf;
}
/**
* @dev Initializes a new buffer from an existing bytes object.
* Changes to the buffer may mutate the original value.
* @param b The bytes object to initialize the buffer with.
* @return A new buffer.
*/
function fromBytes(bytes memory b) internal pure returns(buffer memory) {
buffer memory buf;
buf.buf = b;
buf.capacity = b.length;
return buf;
}
function resize(buffer memory buf, uint capacity) private pure {
bytes memory oldbuf = buf.buf;
init(buf, capacity);
append(buf, oldbuf);
}
/**
* @dev Sets buffer length to 0.
* @param buf The buffer to truncate.
* @return The original buffer, for chaining..
*/
function truncate(buffer memory buf) internal pure returns (buffer memory) {
assembly {
let bufptr := mload(buf)
mstore(bufptr, 0)
}
return buf;
}
/**
* @dev Appends len bytes of a byte string to a buffer. Resizes if doing so would exceed
* the capacity of the buffer.
* @param buf The buffer to append to.
* @param data The data to append.
* @param len The number of bytes to copy.
* @return The original buffer, for chaining.
*/
function append(buffer memory buf, bytes memory data, uint len) internal pure returns(buffer memory) {
require(len <= data.length);
uint off = buf.buf.length;
uint newCapacity = off + len;
if (newCapacity > buf.capacity) {
resize(buf, newCapacity * 2);
}
uint dest;
uint src;
assembly {
// Memory address of the buffer data
let bufptr := mload(buf)
// Length of existing buffer data
let buflen := mload(bufptr)
// Start address = buffer address + offset + sizeof(buffer length)
dest := add(add(bufptr, 32), off)
// Update buffer length if we're extending it
if gt(newCapacity, buflen) {
mstore(bufptr, newCapacity)
}
src := add(data, 32)
}
// Copy word-length chunks while possible
for (; len >= 32; len -= 32) {
assembly {
mstore(dest, mload(src))
}
dest += 32;
src += 32;
}
// Copy remaining bytes
unchecked {
uint mask = (256 ** (32 - len)) - 1;
assembly {
let srcpart := and(mload(src), not(mask))
let destpart := and(mload(dest), mask)
mstore(dest, or(destpart, srcpart))
}
}
return buf;
}
/**
* @dev Appends a byte string to a buffer. Resizes if doing so would exceed
* the capacity of the buffer.
* @param buf The buffer to append to.
* @param data The data to append.
* @return The original buffer, for chaining.
*/
function append(buffer memory buf, bytes memory data) internal pure returns (buffer memory) {
return append(buf, data, data.length);
}
/**
* @dev Appends a byte to the buffer. Resizes if doing so would exceed the
* capacity of the buffer.
* @param buf The buffer to append to.
* @param data The data to append.
* @return The original buffer, for chaining.
*/
function appendUint8(buffer memory buf, uint8 data) internal pure returns(buffer memory) {
uint off = buf.buf.length;
uint offPlusOne = off + 1;
if (off >= buf.capacity) {
resize(buf, offPlusOne * 2);
}
assembly {
// Memory address of the buffer data
let bufptr := mload(buf)
// Address = buffer address + sizeof(buffer length) + off
let dest := add(add(bufptr, off), 32)
mstore8(dest, data)
// Update buffer length if we extended it
if gt(offPlusOne, mload(bufptr)) {
mstore(bufptr, offPlusOne)
}
}
return buf;
}
/**
* @dev Appends len bytes of bytes32 to a buffer. Resizes if doing so would
* exceed the capacity of the buffer.
* @param buf The buffer to append to.
* @param data The data to append.
* @param len The number of bytes to write (left-aligned).
* @return The original buffer, for chaining.
*/
function append(buffer memory buf, bytes32 data, uint len) private pure returns(buffer memory) {
uint off = buf.buf.length;
uint newCapacity = len + off;
if (newCapacity > buf.capacity) {
resize(buf, newCapacity * 2);
}
unchecked {
uint mask = (256 ** len) - 1;
// Right-align data
data = data >> (8 * (32 - len));
assembly {
// Memory address of the buffer data
let bufptr := mload(buf)
// Address = buffer address + sizeof(buffer length) + newCapacity
let dest := add(bufptr, newCapacity)
mstore(dest, or(and(mload(dest), not(mask)), data))
// Update buffer length if we extended it
if gt(newCapacity, mload(bufptr)) {
mstore(bufptr, newCapacity)
}
}
}
return buf;
}
/**
* @dev Appends a bytes20 to the buffer. Resizes if doing so would exceed
* the capacity of the buffer.
* @param buf The buffer to append to.
* @param data The data to append.
* @return The original buffer, for chhaining.
*/
function appendBytes20(buffer memory buf, bytes20 data) internal pure returns (buffer memory) {
return append(buf, bytes32(data), 20);
}
/**
* @dev Appends a bytes32 to the buffer. Resizes if doing so would exceed
* the capacity of the buffer.
* @param buf The buffer to append to.
* @param data The data to append.
* @return The original buffer, for chaining.
*/
function appendBytes32(buffer memory buf, bytes32 data) internal pure returns (buffer memory) {
return append(buf, data, 32);
}
/**
* @dev Appends a byte to the end of the buffer. Resizes if doing so would
* exceed the capacity of the buffer.
* @param buf The buffer to append to.
* @param data The data to append.
* @param len The number of bytes to write (right-aligned).
* @return The original buffer.
*/
function appendInt(buffer memory buf, uint data, uint len) internal pure returns(buffer memory) {
uint off = buf.buf.length;
uint newCapacity = len + off;
if (newCapacity > buf.capacity) {
resize(buf, newCapacity * 2);
}
uint mask = (256 ** len) - 1;
assembly {
// Memory address of the buffer data
let bufptr := mload(buf)
// Address = buffer address + sizeof(buffer length) + newCapacity
let dest := add(bufptr, newCapacity)
mstore(dest, or(and(mload(dest), not(mask)), data))
// Update buffer length if we extended it
if gt(newCapacity, mload(bufptr)) {
mstore(bufptr, newCapacity)
}
}
return buf;
}
}{
"remappings": [
"@openzeppelin/=node_modules/ens-contracts/node_modules/@openzeppelin/",
"frax-std/=node_modules/frax-standard-solidity/src/",
"@prb/test/=node_modules/@prb/test/",
"forge-std/=node_modules/forge-std/src/",
"ds-test/=node_modules/ds-test/src/",
"@chainlink/=node_modules/@chainlink/",
"@ensdomains/=node_modules/@ensdomains/",
"@eth-optimism/=node_modules/@eth-optimism/",
"elliptic-solidity/=node_modules/elliptic-solidity/",
"ens-contracts/=node_modules/ens-contracts/",
"eth-gas-reporter/=node_modules/eth-gas-reporter/",
"frax-standard-solidity/=node_modules/frax-standard-solidity/",
"hardhat-deploy/=node_modules/hardhat-deploy/",
"hardhat/=node_modules/hardhat/",
"solidity-bytes-utils/=node_modules/solidity-bytes-utils/"
],
"optimizer": {
"enabled": true,
"runs": 1300
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "none",
"appendCBOR": false
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "paris",
"viaIR": false,
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"delegationRegistry","type":"address"},{"internalType":"address","name":"initialDelegate","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"contentType","type":"uint256"}],"name":"ABIChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"address","name":"a","type":"address"}],"name":"AddrChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"coinType","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"newAddress","type":"bytes"}],"name":"AddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"hash","type":"bytes"}],"name":"ContenthashChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"name","type":"bytes"},{"indexed":false,"internalType":"uint16","name":"resource","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"record","type":"bytes"}],"name":"DNSRecordChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"name","type":"bytes"},{"indexed":false,"internalType":"uint16","name":"resource","type":"uint16"}],"name":"DNSRecordDeleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"lastzonehash","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"zonehash","type":"bytes"}],"name":"DNSZonehashChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"bytes4","name":"interfaceID","type":"bytes4"},{"indexed":false,"internalType":"address","name":"implementer","type":"address"}],"name":"InterfaceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"string","name":"name","type":"string"}],"name":"NameChanged","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":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"x","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"y","type":"bytes32"}],"name":"PubkeyChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"string","name":"indexedKey","type":"string"},{"indexed":false,"internalType":"string","name":"key","type":"string"},{"indexed":false,"internalType":"string","name":"value","type":"string"}],"name":"TextChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"newVersion","type":"uint64"}],"name":"VersionChanged","type":"event"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"contentTypes","type":"uint256"}],"name":"ABI","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"addr","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"coinType","type":"uint256"}],"name":"addr","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"clearRecords","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"contenthash","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"name","type":"bytes32"},{"internalType":"uint16","name":"resource","type":"uint16"}],"name":"dnsRecord","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"name","type":"bytes32"}],"name":"hasDNSRecords","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes4","name":"interfaceID","type":"bytes4"}],"name":"interfaceImplementer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"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":"pubkey","outputs":[{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"recordVersions","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"resolve","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"contentType","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setABI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"coinType","type":"uint256"},{"internalType":"bytes","name":"a","type":"bytes"}],"name":"setAddr","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"address","name":"a","type":"address"}],"name":"setAddr","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes","name":"hash","type":"bytes"}],"name":"setContenthash","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setDNSRecords","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes4","name":"interfaceID","type":"bytes4"},{"internalType":"address","name":"implementer","type":"address"}],"name":"setInterface","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"newName","type":"string"}],"name":"setName","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"name":"setPubkey","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"key","type":"string"},{"internalType":"string","name":"value","type":"string"}],"name":"setText","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes","name":"hash","type":"bytes"}],"name":"setZonehash","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":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"key","type":"string"}],"name":"text","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"zonehash","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60806040523480156200001157600080fd5b5060405162002c1038038062002c1083398101604081905262000034916200025b565b6200003f33620001ee565b6040516001600160a01b03828116602483015283169060440160408051601f198184030181529181526020820180516001600160e01b03166302b8a21d60e01b179052516200008f919062000293565b6000604051808303816000865af19150503d8060008114620000ce576040519150601f19603f3d011682016040523d82523d6000602084013e620000d3565b606091505b505060408051600481526024810182526020810180516001600160e01b03166325ce9a3760e01b17905290516001600160a01b038516925062000117919062000293565b6000604051808303816000865af19150503d806000811462000156576040519150601f19603f3d011682016040523d82523d6000602084013e6200015b565b606091505b505060408051600481526024810182526020810180516001600160e01b03166353f340a360e11b17905290516001600160a01b03851692506200019f919062000293565b6000604051808303816000865af19150503d8060008114620001de576040519150601f19603f3d011682016040523d82523d6000602084013e620001e3565b606091505b5050505050620002c4565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200025657600080fd5b919050565b600080604083850312156200026f57600080fd5b6200027a836200023e565b91506200028a602084016200023e565b90509250929050565b6000825160005b81811015620002b657602081860181015185830152016200029a565b506000920191825250919050565b61293c80620002d46000396000f3fe608060405234801561001057600080fd5b50600436106101cf5760003560e01c8063691f343111610104578063bc1c58d1116100a2578063d700ff3311610071578063d700ff3314610497578063e59d895d146104da578063f1cb7e06146104ed578063f2fde38b1461050057600080fd5b8063bc1c58d114610404578063c869023314610417578063ce3decdc14610471578063d5fa2b001461048457600080fd5b80638b95dd71116100de5780638b95dd71146103ba5780638da5cb5b146103cd5780639061b923146103de578063a8fa5682146103f157600080fd5b8063691f34311461038c578063715018a61461039f57806377372213146103a757600080fd5b8063304e6ade116101715780634cbf6ba41161014b5780634cbf6ba41461030557806359d1d43c146103535780635c98042b14610366578063623195b01461037957600080fd5b8063304e6ade146102cc5780633603d758146102df5780633b3b57de146102f257600080fd5b806310f13a8c116101ad57806310f13a8c1461025a578063124a319c1461026d5780632203ab561461029857806329cd62ea146102b957600080fd5b806301ffc9a7146101d457806306fdde03146101fc5780630af179d714610245575b600080fd5b6101e76101e23660046120a3565b610513565b60405190151581526020015b60405180910390f35b6102386040518060400160405280601281526020017f464e53204f776e6564205265736f6c766572000000000000000000000000000081525081565b6040516101f3919061210e565b610258610253366004612163565b610524565b005b6102586102683660046121af565b610736565b61028061027b366004612229565b61080b565b6040516001600160a01b0390911681526020016101f3565b6102ab6102a6366004612255565b610ab9565b6040516101f3929190612277565b6102586102c7366004612290565b610bf1565b6102586102da366004612163565b610c99565b6102586102ed3660046122bc565b610d1d565b6102806103003660046122bc565b610dc8565b6101e7610313366004612255565b60008281526001602090815260408083205467ffffffffffffffff1683526007825280832094835293815283822092825291909152205461ffff16151590565b610238610361366004612163565b610dfa565b6102386103743660046122bc565b610edc565b6102586103873660046122d5565b610f9d565b61023861039a3660046122bc565b611042565b61025861107e565b6102586103b5366004612163565b611092565b6102586103c83660046123cb565b611116565b6000546001600160a01b0316610280565b6102386103ec36600461241b565b6111fe565b6102386103ff36600461247f565b611277565b6102386104123660046122bc565b6112c7565b61045c6104253660046122bc565b60008181526001602081815260408084205467ffffffffffffffff168452600a825280842094845293905291902080549101549091565b604080519283526020830191909152016101f3565b61025861047f366004612163565b611303565b6102586104923660046124d6565b61144e565b6104c16104a53660046122bc565b60016020526000908152604090205467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016101f3565b6102586104e83660046124f9565b61147b565b6102386104fb366004612255565b611537565b61025861050e366004612535565b611601565b600061051e82611696565b92915050565b60005483906001600160a01b0316331461053d57600080fd5b6000848152600160209081526040808320548151601f870184900484028101840190925285825283926060928392859267ffffffffffffffff9091169183916105a59183918d908d908190840183828082843760009201919091525092939250506116d49050565b90505b805151602082015110156106cf578661ffff1660000361060d57806040015196506105d281611735565b9450846040516020016105e59190612550565b60405160208183030381529060405280519060200120925061060681611756565b93506106c1565b600061061882611735565b9050816040015161ffff168861ffff1614158061063c575061063a8682611772565b155b156106bf576106988c878a8e8e8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505060208801518d915061068f908290612582565b8b51158a611790565b8160400151975081602001519650809550858051906020012093506106bc82611756565b94505b505b6106ca816119fd565b6105a8565b5083511561072a5761072a8a85888c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508c925061072191508290508f612582565b89511588611790565b50505050505050505050565b60005485906001600160a01b0316331461074f57600080fd5b60008681526001602090815260408083205467ffffffffffffffff168352600b8252808320898452909152908190209051849184916107919089908990612595565b908152602001604051809103902091826107ac92919061262d565b5084846040516107bd929190612595565b6040518091039020867f448bc014f1536726cf8d54ff3d6481ed3cbc683c2591ca204274009afa09b1a1878787876040516107fb9493929190612716565b60405180910390a3505050505050565b60008281526001602090815260408083205467ffffffffffffffff1683526008825280832085845282528083206001600160e01b0319851684529091528120546001600160a01b0316801561086157905061051e565b600061086c85610dc8565b90506001600160a01b0381166108875760009250505061051e565b6040516301ffc9a760e01b602482015260009081906001600160a01b0384169060440160408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166301ffc9a760e01b179052516108f49190612550565b600060405180830381855afa9150503d806000811461092f576040519150601f19603f3d011682016040523d82523d6000602084013e610934565b606091505b5091509150811580610947575060208151105b80610989575080601f8151811061096057610960612748565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016155b1561099b57600094505050505061051e565b6040516001600160e01b0319871660248201526001600160a01b0384169060440160408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166301ffc9a760e01b17905251610a069190612550565b600060405180830381855afa9150503d8060008114610a41576040519150601f19603f3d011682016040523d82523d6000602084013e610a46565b606091505b509092509050811580610a5a575060208151105b80610a9c575080601f81518110610a7357610a73612748565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016155b15610aae57600094505050505061051e565b509095945050505050565b60008281526001602081815260408084205467ffffffffffffffff1684526002825280842086855290915282206060915b848111610bd15780851615801590610b1a575060008181526020839052604081208054610b16906125a5565b9050115b15610bc95780826000838152602001908152602001600020808054610b3e906125a5565b80601f0160208091040260200160405190810160405280929190818152602001828054610b6a906125a5565b8015610bb75780601f10610b8c57610100808354040283529160200191610bb7565b820191906000526020600020905b815481529060010190602001808311610b9a57829003601f168201915b50505050509050935093505050610bea565b60011b610aea565b5060006040518060200160405280600081525092509250505b9250929050565b60005483906001600160a01b03163314610c0a57600080fd5b6040805180820182528481526020808201858152600088815260018084528582205467ffffffffffffffff168252600a84528582208a835290935284902092518355519101555184907f1d6f5e03d3f63eb58751986629a5439baee5079ff04f345becb66e23eb154e4690610c8b9086908690918252602082015260400190565b60405180910390a250505050565b60005483906001600160a01b03163314610cb257600080fd5b60008481526001602090815260408083205467ffffffffffffffff168352600482528083208784529091529020610cea83858361262d565b50837fe379c1624ed7e714cc0937528a32359d69d5281337765313dba4e081b72d75788484604051610c8b92919061275e565b60005481906001600160a01b03163314610d3657600080fd5b6000828152600160205260408120805467ffffffffffffffff1691610d5a83612772565b82546101009290920a67ffffffffffffffff8181021990931691831602179091556000848152600160209081526040918290205491519190921681528492507fc6621ccb8f3f5a04bb6502154b2caf6adf5983fe76dfef1cfc9c42e3579db444910160405180910390a25050565b600080610dd683603c611537565b90508051600003610dea5750600092915050565b610df381611ae5565b9392505050565b60008381526001602090815260408083205467ffffffffffffffff168352600b825280832086845290915290819020905160609190610e3c9085908590612595565b90815260200160405180910390208054610e55906125a5565b80601f0160208091040260200160405190810160405280929190818152602001828054610e81906125a5565b8015610ece5780601f10610ea357610100808354040283529160200191610ece565b820191906000526020600020905b815481529060010190602001808311610eb157829003601f168201915b505050505090509392505050565b60008181526001602090815260408083205467ffffffffffffffff168352600582528083208484529091529020805460609190610f18906125a5565b80601f0160208091040260200160405190810160405280929190818152602001828054610f44906125a5565b8015610f915780601f10610f6657610100808354040283529160200191610f91565b820191906000526020600020905b815481529060010190602001808311610f7457829003601f168201915b50505050509050919050565b60005484906001600160a01b03163314610fb657600080fd5b83610fc2600182612582565b1615610fcd57600080fd5b60008581526001602090815260408083205467ffffffffffffffff168352600282528083208884528252808320878452909152902061100d83858361262d565b50604051849086907faa121bbeef5f32f5961a2a28966e769023910fc9479059ee3495d4c1a696efe390600090a35050505050565b60008181526001602090815260408083205467ffffffffffffffff168352600982528083208484529091529020805460609190610f18906125a5565b611086611b0d565b6110906000611b67565b565b60005483906001600160a01b031633146110ab57600080fd5b60008481526001602090815260408083205467ffffffffffffffff1683526009825280832087845290915290206110e383858361262d565b50837fb7d29e911041e8d9b843369e890bcb72c9388692ba48b65ac54e7214c4c348f78484604051610c8b92919061275e565b60005483906001600160a01b0316331461112f57600080fd5b837f65412581168e88a1e60c6459d7f44ae83ad0832e670826c05a4e2476b57af7528484604051611161929190612277565b60405180910390a2603c83036111b857837f52d7d861f09ab3d26239d492e8968629f95e9e318cf0b73bfddc441522a15fd261119c84611ae5565b6040516001600160a01b03909116815260200160405180910390a25b60008481526001602090815260408083205467ffffffffffffffff16835260038252808320878452825280832086845290915290206111f78382612799565b5050505050565b6060600080306001600160a01b03168460405161121b9190612550565b600060405180830381855afa9150503d8060008114611256576040519150601f19603f3d011682016040523d82523d6000602084013e61125b565b606091505b5091509150811561126f57915061051e9050565b805160208201fd5b60008381526001602090815260408083205467ffffffffffffffff168352600682528083208684528252808320858452825280832061ffff851684529091529020805460609190610e55906125a5565b60008181526001602090815260408083205467ffffffffffffffff168352600482528083208484529091529020805460609190610f18906125a5565b60005483906001600160a01b0316331461131c57600080fd5b60008481526001602090815260408083205467ffffffffffffffff168084526005835281842088855290925282208054919291611358906125a5565b80601f0160208091040260200160405190810160405280929190818152602001828054611384906125a5565b80156113d15780601f106113a6576101008083540402835291602001916113d1565b820191906000526020600020905b8154815290600101906020018083116113b457829003601f168201915b5050505067ffffffffffffffff841660009081526005602090815260408083208b84529091529020919250611409905085878361262d565b50857f8f15ed4b723ef428f250961da8315675b507046737e19319fc1a4d81bfe87f8582878760405161143e93929190612859565b60405180910390a2505050505050565b60005482906001600160a01b0316331461146757600080fd5b61147683603c6103c885611bc4565b505050565b60005483906001600160a01b0316331461149457600080fd5b60008481526001602090815260408083205467ffffffffffffffff1683526008825280832087845282528083206001600160e01b0319871680855290835292819020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038716908117909155905190815286917f7c69f06bea0bdef565b709e93a147836b0063ba2dd89f02d0b7e8d931e6a6daa910160405180910390a350505050565b60008281526001602090815260408083205467ffffffffffffffff168352600382528083208584528252808320848452909152902080546060919061157b906125a5565b80601f01602080910402602001604051908101604052809291908181526020018280546115a7906125a5565b80156115f45780601f106115c9576101008083540402835291602001916115f4565b820191906000526020600020905b8154815290600101906020018083116115d757829003601f168201915b5050505050905092915050565b611609611b0d565b6001600160a01b03811661168a5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61169381611b67565b50565b60006001600160e01b031982167f59d1d43c00000000000000000000000000000000000000000000000000000000148061051e575061051e82611bfd565b6117226040518060e001604052806060815260200160008152602001600061ffff168152602001600061ffff168152602001600063ffffffff16815260200160008152602001600081525090565b82815260c0810182905261051e816119fd565b6020810151815160609161051e9161174d9082611c3b565b84519190611c9d565b60a081015160c082015160609161051e9161174d908290612582565b600081518351148015610df35750610df38360008460008751611d14565b8651602088012060006117a4878787611c9d565b905083156118ce5767ffffffffffffffff831660009081526006602090815260408083208d84528252808320858452825280832061ffff8c168452909152902080546117ef906125a5565b15905061184e5767ffffffffffffffff831660009081526007602090815260408083208d845282528083208584529091528120805461ffff169161183283612889565b91906101000a81548161ffff021916908361ffff160217905550505b67ffffffffffffffff831660009081526006602090815260408083208d84528252808320858452825280832061ffff8c168452909152812061188f91612038565b897f03528ed0c2a3ebc993b12ce3c16bb382f9c7d88ef7d8a1bf290eaf35955a12078a8a6040516118c19291906128a7565b60405180910390a261072a565b67ffffffffffffffff831660009081526006602090815260408083208d84528252808320858452825280832061ffff8c16845290915290208054611911906125a5565b90506000036119725767ffffffffffffffff831660009081526007602090815260408083208d845282528083208584529091528120805461ffff1691611956836128cd565b91906101000a81548161ffff021916908361ffff160217905550505b67ffffffffffffffff831660009081526006602090815260408083208d84528252808320858452825280832061ffff8c16845290915290206119b48282612799565b50897f52a608b3303a48862d07a73d82fa221318c0027fbbcfb1b2329bface3f19ff2b8a8a846040516119e9939291906128e4565b60405180910390a250505050505050505050565b60c08101516020820181905281515111611a145750565b6000611a2882600001518360200151611c3b565b8260200151611a379190612913565b8251909150611a469082611d37565b61ffff166040830152611a5a600282612913565b8251909150611a699082611d37565b61ffff166060830152611a7d600282612913565b8251909150611a8c9082611d5f565b63ffffffff166080830152611aa2600482612913565b8251909150600090611ab49083611d37565b61ffff169050611ac5600283612913565b60a084018190529150611ad88183612913565b60c0909301929092525050565b60008151601414611af557600080fd5b50602001516c01000000000000000000000000900490565b6000546001600160a01b031633146110905760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611681565b600080546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6040805160148082528183019092526060916020820181803683375050506c010000000000000000000000009290920260208301525090565b60006001600160e01b031982167fc869023300000000000000000000000000000000000000000000000000000000148061051e575061051e82611d89565b6000815b83518110611c4f57611c4f612926565b6000611c5b8583611dc7565b60ff169050611c6b816001612913565b611c759083612913565b915080600003611c855750611c8b565b50611c3f565b611c958382612582565b949350505050565b8251606090611cac8385612913565b1115611cb757600080fd5b60008267ffffffffffffffff811115611cd257611cd2612328565b6040519080825280601f01601f191660200182016040528015611cfc576020820181803683370190505b50905060208082019086860101610aae828287611deb565b6000611d21848484611e41565b611d2c878785611e41565b149695505050505050565b8151600090611d47836002612913565b1115611d5257600080fd5b50016002015161ffff1690565b8151600090611d6f836004612913565b1115611d7a57600080fd5b50016004015163ffffffff1690565b60006001600160e01b031982167f691f343100000000000000000000000000000000000000000000000000000000148061051e575061051e82611e65565b6000828281518110611ddb57611ddb612748565b016020015160f81c905092915050565b60208110611e235781518352611e02602084612913565b9250611e0f602083612913565b9150611e1c602082612582565b9050611deb565b905182516020929092036101000a6000190180199091169116179052565b8251600090611e508385612913565b1115611e5b57600080fd5b5091016020012090565b60006001600160e01b031982167f124a319c00000000000000000000000000000000000000000000000000000000148061051e575061051e8260006001600160e01b031982167fa8fa5682000000000000000000000000000000000000000000000000000000001480611f0157506001600160e01b031982167f5c98042b00000000000000000000000000000000000000000000000000000000145b8061051e575061051e8260006001600160e01b031982167fbc1c58d100000000000000000000000000000000000000000000000000000000148061051e575061051e8260006001600160e01b031982167f3b3b57de000000000000000000000000000000000000000000000000000000001480611fa757506001600160e01b031982167ff1cb7e0600000000000000000000000000000000000000000000000000000000145b8061051e575061051e8260006001600160e01b031982167f2203ab5600000000000000000000000000000000000000000000000000000000148061051e575061051e8260006001600160e01b031982167fd700ff3300000000000000000000000000000000000000000000000000000000148061051e57506301ffc9a760e01b6001600160e01b031983161461051e565b508054612044906125a5565b6000825580601f10612054575050565b601f01602090049060005260206000209081019061169391905b80821115612082576000815560010161206e565b5090565b80356001600160e01b03198116811461209e57600080fd5b919050565b6000602082840312156120b557600080fd5b610df382612086565b60005b838110156120d95781810151838201526020016120c1565b50506000910152565b600081518084526120fa8160208601602086016120be565b601f01601f19169290920160200192915050565b602081526000610df360208301846120e2565b60008083601f84011261213357600080fd5b50813567ffffffffffffffff81111561214b57600080fd5b602083019150836020828501011115610bea57600080fd5b60008060006040848603121561217857600080fd5b83359250602084013567ffffffffffffffff81111561219657600080fd5b6121a286828701612121565b9497909650939450505050565b6000806000806000606086880312156121c757600080fd5b85359450602086013567ffffffffffffffff808211156121e657600080fd5b6121f289838a01612121565b9096509450604088013591508082111561220b57600080fd5b5061221888828901612121565b969995985093965092949392505050565b6000806040838503121561223c57600080fd5b8235915061224c60208401612086565b90509250929050565b6000806040838503121561226857600080fd5b50508035926020909101359150565b828152604060208201526000611c9560408301846120e2565b6000806000606084860312156122a557600080fd5b505081359360208301359350604090920135919050565b6000602082840312156122ce57600080fd5b5035919050565b600080600080606085870312156122eb57600080fd5b8435935060208501359250604085013567ffffffffffffffff81111561231057600080fd5b61231c87828801612121565b95989497509550505050565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261234f57600080fd5b813567ffffffffffffffff8082111561236a5761236a612328565b604051601f8301601f19908116603f0116810190828211818310171561239257612392612328565b816040528381528660208588010111156123ab57600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156123e057600080fd5b8335925060208401359150604084013567ffffffffffffffff81111561240557600080fd5b6124118682870161233e565b9150509250925092565b6000806040838503121561242e57600080fd5b823567ffffffffffffffff8082111561244657600080fd5b6124528683870161233e565b9350602085013591508082111561246857600080fd5b506124758582860161233e565b9150509250929050565b60008060006060848603121561249457600080fd5b8335925060208401359150604084013561ffff811681146124b457600080fd5b809150509250925092565b80356001600160a01b038116811461209e57600080fd5b600080604083850312156124e957600080fd5b8235915061224c602084016124bf565b60008060006060848603121561250e57600080fd5b8335925061251e60208501612086565b915061252c604085016124bf565b90509250925092565b60006020828403121561254757600080fd5b610df3826124bf565b600082516125628184602087016120be565b9190910192915050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561051e5761051e61256c565b8183823760009101908152919050565b600181811c908216806125b957607f821691505b6020821081036125d957634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111561147657600081815260208120601f850160051c810160208610156126065750805b601f850160051c820191505b8181101561262557828155600101612612565b505050505050565b67ffffffffffffffff83111561264557612645612328565b6126598361265383546125a5565b836125df565b6000601f84116001811461268d57600085156126755750838201355b600019600387901b1c1916600186901b1783556111f7565b600083815260209020601f19861690835b828110156126be578685013582556020948501946001909201910161269e565b50868210156126db5760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60408152600061272a6040830186886126ed565b828103602084015261273d8185876126ed565b979650505050505050565b634e487b7160e01b600052603260045260246000fd5b602081526000611c956020830184866126ed565b600067ffffffffffffffff80831681810361278f5761278f61256c565b6001019392505050565b815167ffffffffffffffff8111156127b3576127b3612328565b6127c7816127c184546125a5565b846125df565b602080601f8311600181146127fc57600084156127e45750858301515b600019600386901b1c1916600185901b178555612625565b600085815260208120601f198616915b8281101561282b5788860151825594840194600190910190840161280c565b50858210156128495787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60408152600061286c60408301866120e2565b828103602084015261287f8185876126ed565b9695505050505050565b600061ffff82168061289d5761289d61256c565b6000190192915050565b6040815260006128ba60408301856120e2565b905061ffff831660208301529392505050565b600061ffff80831681810361278f5761278f61256c565b6060815260006128f760608301866120e2565b61ffff85166020840152828103604084015261287f81856120e2565b8082018082111561051e5761051e61256c565b634e487b7160e01b600052600160045260246000fd000000000000000000000000f5ca906f05cafa944c27c6881bed3dfd3a785b6a000000000000000000000000c4eb45d80dc1f079045e75d5d55de8ed1c1090e6
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101cf5760003560e01c8063691f343111610104578063bc1c58d1116100a2578063d700ff3311610071578063d700ff3314610497578063e59d895d146104da578063f1cb7e06146104ed578063f2fde38b1461050057600080fd5b8063bc1c58d114610404578063c869023314610417578063ce3decdc14610471578063d5fa2b001461048457600080fd5b80638b95dd71116100de5780638b95dd71146103ba5780638da5cb5b146103cd5780639061b923146103de578063a8fa5682146103f157600080fd5b8063691f34311461038c578063715018a61461039f57806377372213146103a757600080fd5b8063304e6ade116101715780634cbf6ba41161014b5780634cbf6ba41461030557806359d1d43c146103535780635c98042b14610366578063623195b01461037957600080fd5b8063304e6ade146102cc5780633603d758146102df5780633b3b57de146102f257600080fd5b806310f13a8c116101ad57806310f13a8c1461025a578063124a319c1461026d5780632203ab561461029857806329cd62ea146102b957600080fd5b806301ffc9a7146101d457806306fdde03146101fc5780630af179d714610245575b600080fd5b6101e76101e23660046120a3565b610513565b60405190151581526020015b60405180910390f35b6102386040518060400160405280601281526020017f464e53204f776e6564205265736f6c766572000000000000000000000000000081525081565b6040516101f3919061210e565b610258610253366004612163565b610524565b005b6102586102683660046121af565b610736565b61028061027b366004612229565b61080b565b6040516001600160a01b0390911681526020016101f3565b6102ab6102a6366004612255565b610ab9565b6040516101f3929190612277565b6102586102c7366004612290565b610bf1565b6102586102da366004612163565b610c99565b6102586102ed3660046122bc565b610d1d565b6102806103003660046122bc565b610dc8565b6101e7610313366004612255565b60008281526001602090815260408083205467ffffffffffffffff1683526007825280832094835293815283822092825291909152205461ffff16151590565b610238610361366004612163565b610dfa565b6102386103743660046122bc565b610edc565b6102586103873660046122d5565b610f9d565b61023861039a3660046122bc565b611042565b61025861107e565b6102586103b5366004612163565b611092565b6102586103c83660046123cb565b611116565b6000546001600160a01b0316610280565b6102386103ec36600461241b565b6111fe565b6102386103ff36600461247f565b611277565b6102386104123660046122bc565b6112c7565b61045c6104253660046122bc565b60008181526001602081815260408084205467ffffffffffffffff168452600a825280842094845293905291902080549101549091565b604080519283526020830191909152016101f3565b61025861047f366004612163565b611303565b6102586104923660046124d6565b61144e565b6104c16104a53660046122bc565b60016020526000908152604090205467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016101f3565b6102586104e83660046124f9565b61147b565b6102386104fb366004612255565b611537565b61025861050e366004612535565b611601565b600061051e82611696565b92915050565b60005483906001600160a01b0316331461053d57600080fd5b6000848152600160209081526040808320548151601f870184900484028101840190925285825283926060928392859267ffffffffffffffff9091169183916105a59183918d908d908190840183828082843760009201919091525092939250506116d49050565b90505b805151602082015110156106cf578661ffff1660000361060d57806040015196506105d281611735565b9450846040516020016105e59190612550565b60405160208183030381529060405280519060200120925061060681611756565b93506106c1565b600061061882611735565b9050816040015161ffff168861ffff1614158061063c575061063a8682611772565b155b156106bf576106988c878a8e8e8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505060208801518d915061068f908290612582565b8b51158a611790565b8160400151975081602001519650809550858051906020012093506106bc82611756565b94505b505b6106ca816119fd565b6105a8565b5083511561072a5761072a8a85888c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508c925061072191508290508f612582565b89511588611790565b50505050505050505050565b60005485906001600160a01b0316331461074f57600080fd5b60008681526001602090815260408083205467ffffffffffffffff168352600b8252808320898452909152908190209051849184916107919089908990612595565b908152602001604051809103902091826107ac92919061262d565b5084846040516107bd929190612595565b6040518091039020867f448bc014f1536726cf8d54ff3d6481ed3cbc683c2591ca204274009afa09b1a1878787876040516107fb9493929190612716565b60405180910390a3505050505050565b60008281526001602090815260408083205467ffffffffffffffff1683526008825280832085845282528083206001600160e01b0319851684529091528120546001600160a01b0316801561086157905061051e565b600061086c85610dc8565b90506001600160a01b0381166108875760009250505061051e565b6040516301ffc9a760e01b602482015260009081906001600160a01b0384169060440160408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166301ffc9a760e01b179052516108f49190612550565b600060405180830381855afa9150503d806000811461092f576040519150601f19603f3d011682016040523d82523d6000602084013e610934565b606091505b5091509150811580610947575060208151105b80610989575080601f8151811061096057610960612748565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016155b1561099b57600094505050505061051e565b6040516001600160e01b0319871660248201526001600160a01b0384169060440160408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166301ffc9a760e01b17905251610a069190612550565b600060405180830381855afa9150503d8060008114610a41576040519150601f19603f3d011682016040523d82523d6000602084013e610a46565b606091505b509092509050811580610a5a575060208151105b80610a9c575080601f81518110610a7357610a73612748565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016155b15610aae57600094505050505061051e565b509095945050505050565b60008281526001602081815260408084205467ffffffffffffffff1684526002825280842086855290915282206060915b848111610bd15780851615801590610b1a575060008181526020839052604081208054610b16906125a5565b9050115b15610bc95780826000838152602001908152602001600020808054610b3e906125a5565b80601f0160208091040260200160405190810160405280929190818152602001828054610b6a906125a5565b8015610bb75780601f10610b8c57610100808354040283529160200191610bb7565b820191906000526020600020905b815481529060010190602001808311610b9a57829003601f168201915b50505050509050935093505050610bea565b60011b610aea565b5060006040518060200160405280600081525092509250505b9250929050565b60005483906001600160a01b03163314610c0a57600080fd5b6040805180820182528481526020808201858152600088815260018084528582205467ffffffffffffffff168252600a84528582208a835290935284902092518355519101555184907f1d6f5e03d3f63eb58751986629a5439baee5079ff04f345becb66e23eb154e4690610c8b9086908690918252602082015260400190565b60405180910390a250505050565b60005483906001600160a01b03163314610cb257600080fd5b60008481526001602090815260408083205467ffffffffffffffff168352600482528083208784529091529020610cea83858361262d565b50837fe379c1624ed7e714cc0937528a32359d69d5281337765313dba4e081b72d75788484604051610c8b92919061275e565b60005481906001600160a01b03163314610d3657600080fd5b6000828152600160205260408120805467ffffffffffffffff1691610d5a83612772565b82546101009290920a67ffffffffffffffff8181021990931691831602179091556000848152600160209081526040918290205491519190921681528492507fc6621ccb8f3f5a04bb6502154b2caf6adf5983fe76dfef1cfc9c42e3579db444910160405180910390a25050565b600080610dd683603c611537565b90508051600003610dea5750600092915050565b610df381611ae5565b9392505050565b60008381526001602090815260408083205467ffffffffffffffff168352600b825280832086845290915290819020905160609190610e3c9085908590612595565b90815260200160405180910390208054610e55906125a5565b80601f0160208091040260200160405190810160405280929190818152602001828054610e81906125a5565b8015610ece5780601f10610ea357610100808354040283529160200191610ece565b820191906000526020600020905b815481529060010190602001808311610eb157829003601f168201915b505050505090509392505050565b60008181526001602090815260408083205467ffffffffffffffff168352600582528083208484529091529020805460609190610f18906125a5565b80601f0160208091040260200160405190810160405280929190818152602001828054610f44906125a5565b8015610f915780601f10610f6657610100808354040283529160200191610f91565b820191906000526020600020905b815481529060010190602001808311610f7457829003601f168201915b50505050509050919050565b60005484906001600160a01b03163314610fb657600080fd5b83610fc2600182612582565b1615610fcd57600080fd5b60008581526001602090815260408083205467ffffffffffffffff168352600282528083208884528252808320878452909152902061100d83858361262d565b50604051849086907faa121bbeef5f32f5961a2a28966e769023910fc9479059ee3495d4c1a696efe390600090a35050505050565b60008181526001602090815260408083205467ffffffffffffffff168352600982528083208484529091529020805460609190610f18906125a5565b611086611b0d565b6110906000611b67565b565b60005483906001600160a01b031633146110ab57600080fd5b60008481526001602090815260408083205467ffffffffffffffff1683526009825280832087845290915290206110e383858361262d565b50837fb7d29e911041e8d9b843369e890bcb72c9388692ba48b65ac54e7214c4c348f78484604051610c8b92919061275e565b60005483906001600160a01b0316331461112f57600080fd5b837f65412581168e88a1e60c6459d7f44ae83ad0832e670826c05a4e2476b57af7528484604051611161929190612277565b60405180910390a2603c83036111b857837f52d7d861f09ab3d26239d492e8968629f95e9e318cf0b73bfddc441522a15fd261119c84611ae5565b6040516001600160a01b03909116815260200160405180910390a25b60008481526001602090815260408083205467ffffffffffffffff16835260038252808320878452825280832086845290915290206111f78382612799565b5050505050565b6060600080306001600160a01b03168460405161121b9190612550565b600060405180830381855afa9150503d8060008114611256576040519150601f19603f3d011682016040523d82523d6000602084013e61125b565b606091505b5091509150811561126f57915061051e9050565b805160208201fd5b60008381526001602090815260408083205467ffffffffffffffff168352600682528083208684528252808320858452825280832061ffff851684529091529020805460609190610e55906125a5565b60008181526001602090815260408083205467ffffffffffffffff168352600482528083208484529091529020805460609190610f18906125a5565b60005483906001600160a01b0316331461131c57600080fd5b60008481526001602090815260408083205467ffffffffffffffff168084526005835281842088855290925282208054919291611358906125a5565b80601f0160208091040260200160405190810160405280929190818152602001828054611384906125a5565b80156113d15780601f106113a6576101008083540402835291602001916113d1565b820191906000526020600020905b8154815290600101906020018083116113b457829003601f168201915b5050505067ffffffffffffffff841660009081526005602090815260408083208b84529091529020919250611409905085878361262d565b50857f8f15ed4b723ef428f250961da8315675b507046737e19319fc1a4d81bfe87f8582878760405161143e93929190612859565b60405180910390a2505050505050565b60005482906001600160a01b0316331461146757600080fd5b61147683603c6103c885611bc4565b505050565b60005483906001600160a01b0316331461149457600080fd5b60008481526001602090815260408083205467ffffffffffffffff1683526008825280832087845282528083206001600160e01b0319871680855290835292819020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038716908117909155905190815286917f7c69f06bea0bdef565b709e93a147836b0063ba2dd89f02d0b7e8d931e6a6daa910160405180910390a350505050565b60008281526001602090815260408083205467ffffffffffffffff168352600382528083208584528252808320848452909152902080546060919061157b906125a5565b80601f01602080910402602001604051908101604052809291908181526020018280546115a7906125a5565b80156115f45780601f106115c9576101008083540402835291602001916115f4565b820191906000526020600020905b8154815290600101906020018083116115d757829003601f168201915b5050505050905092915050565b611609611b0d565b6001600160a01b03811661168a5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61169381611b67565b50565b60006001600160e01b031982167f59d1d43c00000000000000000000000000000000000000000000000000000000148061051e575061051e82611bfd565b6117226040518060e001604052806060815260200160008152602001600061ffff168152602001600061ffff168152602001600063ffffffff16815260200160008152602001600081525090565b82815260c0810182905261051e816119fd565b6020810151815160609161051e9161174d9082611c3b565b84519190611c9d565b60a081015160c082015160609161051e9161174d908290612582565b600081518351148015610df35750610df38360008460008751611d14565b8651602088012060006117a4878787611c9d565b905083156118ce5767ffffffffffffffff831660009081526006602090815260408083208d84528252808320858452825280832061ffff8c168452909152902080546117ef906125a5565b15905061184e5767ffffffffffffffff831660009081526007602090815260408083208d845282528083208584529091528120805461ffff169161183283612889565b91906101000a81548161ffff021916908361ffff160217905550505b67ffffffffffffffff831660009081526006602090815260408083208d84528252808320858452825280832061ffff8c168452909152812061188f91612038565b897f03528ed0c2a3ebc993b12ce3c16bb382f9c7d88ef7d8a1bf290eaf35955a12078a8a6040516118c19291906128a7565b60405180910390a261072a565b67ffffffffffffffff831660009081526006602090815260408083208d84528252808320858452825280832061ffff8c16845290915290208054611911906125a5565b90506000036119725767ffffffffffffffff831660009081526007602090815260408083208d845282528083208584529091528120805461ffff1691611956836128cd565b91906101000a81548161ffff021916908361ffff160217905550505b67ffffffffffffffff831660009081526006602090815260408083208d84528252808320858452825280832061ffff8c16845290915290206119b48282612799565b50897f52a608b3303a48862d07a73d82fa221318c0027fbbcfb1b2329bface3f19ff2b8a8a846040516119e9939291906128e4565b60405180910390a250505050505050505050565b60c08101516020820181905281515111611a145750565b6000611a2882600001518360200151611c3b565b8260200151611a379190612913565b8251909150611a469082611d37565b61ffff166040830152611a5a600282612913565b8251909150611a699082611d37565b61ffff166060830152611a7d600282612913565b8251909150611a8c9082611d5f565b63ffffffff166080830152611aa2600482612913565b8251909150600090611ab49083611d37565b61ffff169050611ac5600283612913565b60a084018190529150611ad88183612913565b60c0909301929092525050565b60008151601414611af557600080fd5b50602001516c01000000000000000000000000900490565b6000546001600160a01b031633146110905760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611681565b600080546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6040805160148082528183019092526060916020820181803683375050506c010000000000000000000000009290920260208301525090565b60006001600160e01b031982167fc869023300000000000000000000000000000000000000000000000000000000148061051e575061051e82611d89565b6000815b83518110611c4f57611c4f612926565b6000611c5b8583611dc7565b60ff169050611c6b816001612913565b611c759083612913565b915080600003611c855750611c8b565b50611c3f565b611c958382612582565b949350505050565b8251606090611cac8385612913565b1115611cb757600080fd5b60008267ffffffffffffffff811115611cd257611cd2612328565b6040519080825280601f01601f191660200182016040528015611cfc576020820181803683370190505b50905060208082019086860101610aae828287611deb565b6000611d21848484611e41565b611d2c878785611e41565b149695505050505050565b8151600090611d47836002612913565b1115611d5257600080fd5b50016002015161ffff1690565b8151600090611d6f836004612913565b1115611d7a57600080fd5b50016004015163ffffffff1690565b60006001600160e01b031982167f691f343100000000000000000000000000000000000000000000000000000000148061051e575061051e82611e65565b6000828281518110611ddb57611ddb612748565b016020015160f81c905092915050565b60208110611e235781518352611e02602084612913565b9250611e0f602083612913565b9150611e1c602082612582565b9050611deb565b905182516020929092036101000a6000190180199091169116179052565b8251600090611e508385612913565b1115611e5b57600080fd5b5091016020012090565b60006001600160e01b031982167f124a319c00000000000000000000000000000000000000000000000000000000148061051e575061051e8260006001600160e01b031982167fa8fa5682000000000000000000000000000000000000000000000000000000001480611f0157506001600160e01b031982167f5c98042b00000000000000000000000000000000000000000000000000000000145b8061051e575061051e8260006001600160e01b031982167fbc1c58d100000000000000000000000000000000000000000000000000000000148061051e575061051e8260006001600160e01b031982167f3b3b57de000000000000000000000000000000000000000000000000000000001480611fa757506001600160e01b031982167ff1cb7e0600000000000000000000000000000000000000000000000000000000145b8061051e575061051e8260006001600160e01b031982167f2203ab5600000000000000000000000000000000000000000000000000000000148061051e575061051e8260006001600160e01b031982167fd700ff3300000000000000000000000000000000000000000000000000000000148061051e57506301ffc9a760e01b6001600160e01b031983161461051e565b508054612044906125a5565b6000825580601f10612054575050565b601f01602090049060005260206000209081019061169391905b80821115612082576000815560010161206e565b5090565b80356001600160e01b03198116811461209e57600080fd5b919050565b6000602082840312156120b557600080fd5b610df382612086565b60005b838110156120d95781810151838201526020016120c1565b50506000910152565b600081518084526120fa8160208601602086016120be565b601f01601f19169290920160200192915050565b602081526000610df360208301846120e2565b60008083601f84011261213357600080fd5b50813567ffffffffffffffff81111561214b57600080fd5b602083019150836020828501011115610bea57600080fd5b60008060006040848603121561217857600080fd5b83359250602084013567ffffffffffffffff81111561219657600080fd5b6121a286828701612121565b9497909650939450505050565b6000806000806000606086880312156121c757600080fd5b85359450602086013567ffffffffffffffff808211156121e657600080fd5b6121f289838a01612121565b9096509450604088013591508082111561220b57600080fd5b5061221888828901612121565b969995985093965092949392505050565b6000806040838503121561223c57600080fd5b8235915061224c60208401612086565b90509250929050565b6000806040838503121561226857600080fd5b50508035926020909101359150565b828152604060208201526000611c9560408301846120e2565b6000806000606084860312156122a557600080fd5b505081359360208301359350604090920135919050565b6000602082840312156122ce57600080fd5b5035919050565b600080600080606085870312156122eb57600080fd5b8435935060208501359250604085013567ffffffffffffffff81111561231057600080fd5b61231c87828801612121565b95989497509550505050565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261234f57600080fd5b813567ffffffffffffffff8082111561236a5761236a612328565b604051601f8301601f19908116603f0116810190828211818310171561239257612392612328565b816040528381528660208588010111156123ab57600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156123e057600080fd5b8335925060208401359150604084013567ffffffffffffffff81111561240557600080fd5b6124118682870161233e565b9150509250925092565b6000806040838503121561242e57600080fd5b823567ffffffffffffffff8082111561244657600080fd5b6124528683870161233e565b9350602085013591508082111561246857600080fd5b506124758582860161233e565b9150509250929050565b60008060006060848603121561249457600080fd5b8335925060208401359150604084013561ffff811681146124b457600080fd5b809150509250925092565b80356001600160a01b038116811461209e57600080fd5b600080604083850312156124e957600080fd5b8235915061224c602084016124bf565b60008060006060848603121561250e57600080fd5b8335925061251e60208501612086565b915061252c604085016124bf565b90509250925092565b60006020828403121561254757600080fd5b610df3826124bf565b600082516125628184602087016120be565b9190910192915050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561051e5761051e61256c565b8183823760009101908152919050565b600181811c908216806125b957607f821691505b6020821081036125d957634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111561147657600081815260208120601f850160051c810160208610156126065750805b601f850160051c820191505b8181101561262557828155600101612612565b505050505050565b67ffffffffffffffff83111561264557612645612328565b6126598361265383546125a5565b836125df565b6000601f84116001811461268d57600085156126755750838201355b600019600387901b1c1916600186901b1783556111f7565b600083815260209020601f19861690835b828110156126be578685013582556020948501946001909201910161269e565b50868210156126db5760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60408152600061272a6040830186886126ed565b828103602084015261273d8185876126ed565b979650505050505050565b634e487b7160e01b600052603260045260246000fd5b602081526000611c956020830184866126ed565b600067ffffffffffffffff80831681810361278f5761278f61256c565b6001019392505050565b815167ffffffffffffffff8111156127b3576127b3612328565b6127c7816127c184546125a5565b846125df565b602080601f8311600181146127fc57600084156127e45750858301515b600019600386901b1c1916600185901b178555612625565b600085815260208120601f198616915b8281101561282b5788860151825594840194600190910190840161280c565b50858210156128495787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60408152600061286c60408301866120e2565b828103602084015261287f8185876126ed565b9695505050505050565b600061ffff82168061289d5761289d61256c565b6000190192915050565b6040815260006128ba60408301856120e2565b905061ffff831660208301529392505050565b600061ffff80831681810361278f5761278f61256c565b6060815260006128f760608301866120e2565b61ffff85166020840152828103604084015261287f81856120e2565b8082018082111561051e5761051e61256c565b634e487b7160e01b600052600160045260246000fd
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000f5ca906f05cafa944c27c6881bed3dfd3a785b6a000000000000000000000000c4eb45d80dc1f079045e75d5d55de8ed1c1090e6
-----Decoded View---------------
Arg [0] : delegationRegistry (address): 0xF5cA906f05cafa944c27c6881bed3DFd3a785b6A
Arg [1] : initialDelegate (address): 0xC4EB45d80DC1F079045E75D5d55de8eD1c1090E6
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000f5ca906f05cafa944c27c6881bed3dfd3a785b6a
Arg [1] : 000000000000000000000000c4eb45d80dc1f079045e75d5d55de8ed1c1090e6
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in FRAX
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.