More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 93 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Set Addr | 29309099 | 4 mins ago | IN | 0 ETH | 0.00000011 | ||||
Multicall With N... | 29308449 | 26 mins ago | IN | 0 ETH | 0.00000072 | ||||
Multicall With N... | 29302225 | 3 hrs ago | IN | 0 ETH | 0.00000016 | ||||
Multicall With N... | 29301786 | 4 hrs ago | IN | 0 ETH | 0.00000027 | ||||
Multicall With N... | 29300845 | 4 hrs ago | IN | 0 ETH | 0.00000055 | ||||
Set Text | 29300257 | 4 hrs ago | IN | 0 ETH | 0.00000128 | ||||
Multicall With N... | 29299753 | 5 hrs ago | IN | 0 ETH | 0.00000024 | ||||
Multicall With N... | 29299742 | 5 hrs ago | IN | 0 ETH | 0.00000085 | ||||
Multicall With N... | 29299727 | 5 hrs ago | IN | 0 ETH | 0.0000002 | ||||
Multicall With N... | 29299712 | 5 hrs ago | IN | 0 ETH | 0.0000001 | ||||
Multicall With N... | 29299698 | 5 hrs ago | IN | 0 ETH | 0.00000021 | ||||
Multicall With N... | 29299682 | 5 hrs ago | IN | 0 ETH | 0.00000011 | ||||
Multicall With N... | 29299667 | 5 hrs ago | IN | 0 ETH | 0.00000013 | ||||
Multicall With N... | 29299655 | 5 hrs ago | IN | 0 ETH | 0.0000001 | ||||
Multicall With N... | 29299640 | 5 hrs ago | IN | 0 ETH | 0.00000013 | ||||
Multicall With N... | 29299199 | 5 hrs ago | IN | 0 ETH | 0.00000015 | ||||
Multicall With N... | 29299169 | 5 hrs ago | IN | 0 ETH | 0.00000077 | ||||
Multicall With N... | 29297042 | 6 hrs ago | IN | 0 ETH | 0.00000016 | ||||
Set Addr | 29296996 | 6 hrs ago | IN | 0 ETH | 0.00000008 | ||||
Multicall With N... | 29296624 | 7 hrs ago | IN | 0 ETH | 0.00000021 | ||||
Set Addr | 29292386 | 9 hrs ago | IN | 0 ETH | 0.00000009 | ||||
Set Addr | 29291692 | 9 hrs ago | IN | 0 ETH | 0.0000001 | ||||
Multicall With N... | 29288287 | 11 hrs ago | IN | 0 ETH | 0.00000055 | ||||
Set Addr | 29287562 | 12 hrs ago | IN | 0 ETH | 0.00000013 | ||||
Multicall With N... | 29287141 | 12 hrs ago | IN | 0 ETH | 0.00000035 |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
L2Resolver
Compiler Version
v0.8.23+commit.f704f362
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.23; import {ABIResolver} from "ens-contracts/resolvers/profiles/ABIResolver.sol"; import {AddrResolver} from "ens-contracts/resolvers/profiles/AddrResolver.sol"; import {ContentHashResolver} from "ens-contracts/resolvers/profiles/ContentHashResolver.sol"; import {DNSResolver} from "ens-contracts/resolvers/profiles/DNSResolver.sol"; import {ENS} from "ens-contracts/registry/ENS.sol"; import {ExtendedResolver} from "ens-contracts/resolvers/profiles/ExtendedResolver.sol"; import {IExtendedResolver} from "ens-contracts/resolvers/profiles/IExtendedResolver.sol"; import {InterfaceResolver} from "ens-contracts/resolvers/profiles/InterfaceResolver.sol"; import {Multicallable} from "ens-contracts/resolvers/Multicallable.sol"; import {Ownable} from "solady/auth/Ownable.sol"; import {NameResolver} from "ens-contracts/resolvers/profiles/NameResolver.sol"; import {PubkeyResolver} from "ens-contracts/resolvers/profiles/PubkeyResolver.sol"; import {TextResolver} from "ens-contracts/resolvers/profiles/TextResolver.sol"; import {IReverseRegistrar} from "src/L2/interface/IReverseRegistrar.sol"; /// @title L2 Resolver /// /// @notice The default resolver for the Base Usernames project. This contract implements the functionality of the ENS /// PublicResolver while also inheriting ExtendedResolver for compatibility with CCIP-read. /// Public Resolver: https://github.com/ensdomains/ens-contracts/blob/staging/contracts/resolvers/PublicResolver.sol /// Extended Resolver: https://github.com/ensdomains/ens-contracts/blob/staging/contracts/resolvers/profiles/ExtendedResolver.sol /// /// @author Coinbase (https://github.com/base-org/usernames) /// @author ENS (https://github.com/ensdomains/ens-contracts/tree/staging) contract L2Resolver is Multicallable, ABIResolver, AddrResolver, ContentHashResolver, DNSResolver, InterfaceResolver, NameResolver, PubkeyResolver, TextResolver, ExtendedResolver, Ownable { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STORAGE */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @notice The ENS registry. ENS public immutable ens; /// @notice The trusted registrar controller contract. address public registrarController; /// @notice The reverse registrar contract. address public reverseRegistrar; /// @notice A mapping of operators per owner address. An operator is authorized to make changes to /// all names owned by the `owner`. mapping(address owner => mapping(address operator => bool isApproved)) private _operatorApprovals; /// @notice A mapping of delegates per owner per name (stored as a node). A delegate that is authorised /// by an owner for a name may make changes to the name's resolver. mapping(address owner => mapping(bytes32 node => mapping(address delegate => bool isApproved))) private _tokenApprovals; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @notice Thown when msg.sender tries to set itself as an operator. error CantSetSelfAsOperator(); /// @notice Thrown when msg.sender tries to set itself as a delegate for one of its names. error CantSetSelfAsDelegate(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EVENTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @notice Emitted when an operator is added or removed. /// /// @param owner The address of the owner of names. /// @param operator The address of the approved operator for the `owner`. /// @param approved Whether the `operator` is approved or not. event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /// @notice Emitted when a delegate is approved or an approval is revoked. /// /// @param owner The address of the owner of the name. /// @param node The namehash of the name. /// @param delegate The address of the operator for the specified `node`. /// @param approved Whether the `delegate` is approved for the specified `node`. event Approved(address owner, bytes32 indexed node, address indexed delegate, bool indexed approved); /// @notice Emitted when the owner of this contract updates the Registrar Controller addrress. /// /// @param newRegistrarController The address of the new RegistrarController contract. event RegistrarControllerUpdated(address indexed newRegistrarController); /// @notice Emitted when the owner of this contract updates the Reverse Registrar address. /// /// @param newReverseRegistrar The address of the new ReverseRegistrar contract. event ReverseRegistrarUpdated(address indexed newReverseRegistrar); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* IMPLEMENTATION */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @notice L2 Resolver constructor used to establish the necessary contract configuration. /// /// @param ens_ The Registry contract. /// @param registrarController_ The address of the RegistrarController contract. /// @param reverseRegistrar_ The address of the ReverseRegistrar contract. /// @param owner_ The permissioned address initialized as the `owner` in the `Ownable` context. constructor(ENS ens_, address registrarController_, address reverseRegistrar_, address owner_) { ens = ens_; registrarController = registrarController_; reverseRegistrar = reverseRegistrar_; _initializeOwner(owner_); IReverseRegistrar(reverseRegistrar_).claim(owner_); } /// @notice Allows the `owner` to set the registrar controller contract address. /// /// @dev Emits `RegistrarControllerUpdated` after setting the `registrarController` address. /// /// @param registrarController_ The address of the new RegistrarController contract. function setRegistrarController(address registrarController_) external onlyOwner { registrarController = registrarController_; emit RegistrarControllerUpdated(registrarController_); } /// @notice Allows the `owner` to set the reverse registrar contract address. /// /// @dev Emits `ReverseRegistrarUpdated` after setting the `reverseRegistrar` address. /// /// @param reverseRegistrar_ The address of the new ReverseRegistrar contract. function setReverseRegistrar(address reverseRegistrar_) external onlyOwner { reverseRegistrar = reverseRegistrar_; emit ReverseRegistrarUpdated(reverseRegistrar_); } /// @dev See {IERC1155-setApprovalForAll}. function setApprovalForAll(address operator, bool approved) external { if (msg.sender == operator) revert CantSetSelfAsOperator(); _operatorApprovals[msg.sender][operator] = approved; emit ApprovalForAll(msg.sender, operator, approved); } /// @dev See {IERC1155-isApprovedForAll}. function isApprovedForAll(address account, address operator) public view returns (bool) { return _operatorApprovals[account][operator]; } /// @notice Modify the permissions for a specified `delegate` for the specified `node`. /// /// @dev This method only sets the approval status for msg.sender's nodes. This is performed without checking /// the ownership of the specified `node`. /// /// @param node The namehash `node` whose permissions are being updated. /// @param delegate The address of the `delegate` /// @param approved Whether the `delegate` has approval to modify records for `msg.sender`'s `node`. function approve(bytes32 node, address delegate, bool approved) external { if (msg.sender == delegate) revert CantSetSelfAsDelegate(); _tokenApprovals[msg.sender][node][delegate] = approved; emit Approved(msg.sender, node, delegate, approved); } /// @notice Check to see if the `delegate` has been approved by the `owner` for the `node`. /// /// @param owner The address of the name owner. /// @param node The namehash `node` whose permissions are being checked. /// @param delegate The address of the `delegate` whose permissions are being checked. /// /// @return `true` if `delegate` is approved to modify `msg.sender`'s `node`, else `false`. function isApprovedFor(address owner, bytes32 node, address delegate) public view returns (bool) { return _tokenApprovals[owner][node][delegate]; } /// @notice Check to see whether `msg.sender` is authorized to modify records for the specified `node`. /// /// @dev Override for `ResolverBase:isAuthorised()`. Used in the context of each inherited resolver "profile". /// Validates that `msg.sender` is one of: /// 1. The stored registrarController (for setting records upon registration) /// 2 The stored reverseRegistrar (for setting reverse records) /// 3. The owner of the node in the Registry /// 4. An approved operator for owner /// 5. An approved delegate for owner of the specified `node` /// /// @param node The namehashed `node` being authorized. /// /// @return `true` if `msg.sender` is authorized to modify records for the specified `node`, else `false`. function isAuthorised(bytes32 node) internal view override returns (bool) { if (msg.sender == registrarController || msg.sender == reverseRegistrar) { return true; } address owner = ens.owner(node); return owner == msg.sender || isApprovedForAll(owner, msg.sender) || isApprovedFor(owner, node, msg.sender); } /// @notice ERC165 compliant signal for interface support. /// /// @dev Checks interface support for each inherited resolver profile /// https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] /// /// @param interfaceID the ERC165 iface id being checked for compliance /// /// @return bool Whether this contract supports the provided interfaceID function supportsInterface(bytes4 interfaceID) public view override( Multicallable, ABIResolver, AddrResolver, ContentHashResolver, DNSResolver, InterfaceResolver, NameResolver, PubkeyResolver, TextResolver ) returns (bool) { return (interfaceID == type(IExtendedResolver).interfaceId || super.supportsInterface(interfaceID)); } }
// 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); } } }
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 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 IExtendedResolver { function resolve( bytes memory name, bytes memory data ) external view returns (bytes memory); }
// 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 "./IMulticallable.sol"; import "@openzeppelin/contracts/utils/introspection/ERC165.sol"; abstract contract Multicallable is IMulticallable, ERC165 { function _multicall( bytes32 nodehash, bytes[] calldata data ) internal returns (bytes[] memory results) { results = new bytes[](data.length); for (uint256 i = 0; i < data.length; i++) { if (nodehash != bytes32(0)) { bytes32 txNamehash = bytes32(data[i][4:36]); require( txNamehash == nodehash, "multicall: All records must have a matching namehash" ); } (bool success, bytes memory result) = address(this).delegatecall( data[i] ); require(success); results[i] = result; } return results; } // This function provides an extra security check when called // from priviledged contracts (such as EthRegistrarController) // that can set records on behalf of the node owners function multicallWithNodeCheck( bytes32 nodehash, bytes[] calldata data ) external returns (bytes[] memory results) { return _multicall(nodehash, data); } function multicall( bytes[] calldata data ) public override returns (bytes[] memory results) { return _multicall(bytes32(0), data); } function supportsInterface( bytes4 interfaceID ) public view virtual override returns (bool) { return interfaceID == type(IMulticallable).interfaceId || super.supportsInterface(interfaceID); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Simple single owner authorization mixin. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol) /// /// @dev Note: /// This implementation does NOT auto-initialize the owner to `msg.sender`. /// You MUST call the `_initializeOwner` in the constructor / initializer. /// /// While the ownable portion follows /// [EIP-173](https://eips.ethereum.org/EIPS/eip-173) for compatibility, /// the nomenclature for the 2-step ownership handover may be unique to this codebase. abstract contract Ownable { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The caller is not authorized to call the function. error Unauthorized(); /// @dev The `newOwner` cannot be the zero address. error NewOwnerIsZeroAddress(); /// @dev The `pendingOwner` does not have a valid handover request. error NoHandoverRequest(); /// @dev Cannot double-initialize. error AlreadyInitialized(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EVENTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The ownership is transferred from `oldOwner` to `newOwner`. /// This event is intentionally kept the same as OpenZeppelin's Ownable to be /// compatible with indexers and [EIP-173](https://eips.ethereum.org/EIPS/eip-173), /// despite it not being as lightweight as a single argument event. event OwnershipTransferred(address indexed oldOwner, address indexed newOwner); /// @dev An ownership handover to `pendingOwner` has been requested. event OwnershipHandoverRequested(address indexed pendingOwner); /// @dev The ownership handover to `pendingOwner` has been canceled. event OwnershipHandoverCanceled(address indexed pendingOwner); /// @dev `keccak256(bytes("OwnershipTransferred(address,address)"))`. uint256 private constant _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE = 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0; /// @dev `keccak256(bytes("OwnershipHandoverRequested(address)"))`. uint256 private constant _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE = 0xdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d; /// @dev `keccak256(bytes("OwnershipHandoverCanceled(address)"))`. uint256 private constant _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE = 0xfa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STORAGE */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The owner slot is given by: /// `bytes32(~uint256(uint32(bytes4(keccak256("_OWNER_SLOT_NOT")))))`. /// It is intentionally chosen to be a high value /// to avoid collision with lower slots. /// The choice of manual storage layout is to enable compatibility /// with both regular and upgradeable contracts. bytes32 internal constant _OWNER_SLOT = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927; /// The ownership handover slot of `newOwner` is given by: /// ``` /// mstore(0x00, or(shl(96, user), _HANDOVER_SLOT_SEED)) /// let handoverSlot := keccak256(0x00, 0x20) /// ``` /// It stores the expiry timestamp of the two-step ownership handover. uint256 private constant _HANDOVER_SLOT_SEED = 0x389a75e1; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Override to return true to make `_initializeOwner` prevent double-initialization. function _guardInitializeOwner() internal pure virtual returns (bool guard) {} /// @dev Initializes the owner directly without authorization guard. /// This function must be called upon initialization, /// regardless of whether the contract is upgradeable or not. /// This is to enable generalization to both regular and upgradeable contracts, /// and to save gas in case the initial owner is not the caller. /// For performance reasons, this function will not check if there /// is an existing owner. function _initializeOwner(address newOwner) internal virtual { if (_guardInitializeOwner()) { /// @solidity memory-safe-assembly assembly { let ownerSlot := _OWNER_SLOT if sload(ownerSlot) { mstore(0x00, 0x0dc149f0) // `AlreadyInitialized()`. revert(0x1c, 0x04) } // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Store the new value. sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner)))) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner) } } else { /// @solidity memory-safe-assembly assembly { // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Store the new value. sstore(_OWNER_SLOT, newOwner) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner) } } } /// @dev Sets the owner directly without authorization guard. function _setOwner(address newOwner) internal virtual { if (_guardInitializeOwner()) { /// @solidity memory-safe-assembly assembly { let ownerSlot := _OWNER_SLOT // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner) // Store the new value. sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner)))) } } else { /// @solidity memory-safe-assembly assembly { let ownerSlot := _OWNER_SLOT // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner) // Store the new value. sstore(ownerSlot, newOwner) } } } /// @dev Throws if the sender is not the owner. function _checkOwner() internal view virtual { /// @solidity memory-safe-assembly assembly { // If the caller is not the stored owner, revert. if iszero(eq(caller(), sload(_OWNER_SLOT))) { mstore(0x00, 0x82b42900) // `Unauthorized()`. revert(0x1c, 0x04) } } } /// @dev Returns how long a two-step ownership handover is valid for in seconds. /// Override to return a different value if needed. /// Made internal to conserve bytecode. Wrap it in a public function if needed. function _ownershipHandoverValidFor() internal view virtual returns (uint64) { return 48 * 3600; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PUBLIC UPDATE FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Allows the owner to transfer the ownership to `newOwner`. function transferOwnership(address newOwner) public payable virtual onlyOwner { /// @solidity memory-safe-assembly assembly { if iszero(shl(96, newOwner)) { mstore(0x00, 0x7448fbae) // `NewOwnerIsZeroAddress()`. revert(0x1c, 0x04) } } _setOwner(newOwner); } /// @dev Allows the owner to renounce their ownership. function renounceOwnership() public payable virtual onlyOwner { _setOwner(address(0)); } /// @dev Request a two-step ownership handover to the caller. /// The request will automatically expire in 48 hours (172800 seconds) by default. function requestOwnershipHandover() public payable virtual { unchecked { uint256 expires = block.timestamp + _ownershipHandoverValidFor(); /// @solidity memory-safe-assembly assembly { // Compute and set the handover slot to `expires`. mstore(0x0c, _HANDOVER_SLOT_SEED) mstore(0x00, caller()) sstore(keccak256(0x0c, 0x20), expires) // Emit the {OwnershipHandoverRequested} event. log2(0, 0, _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE, caller()) } } } /// @dev Cancels the two-step ownership handover to the caller, if any. function cancelOwnershipHandover() public payable virtual { /// @solidity memory-safe-assembly assembly { // Compute and set the handover slot to 0. mstore(0x0c, _HANDOVER_SLOT_SEED) mstore(0x00, caller()) sstore(keccak256(0x0c, 0x20), 0) // Emit the {OwnershipHandoverCanceled} event. log2(0, 0, _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE, caller()) } } /// @dev Allows the owner to complete the two-step ownership handover to `pendingOwner`. /// Reverts if there is no existing ownership handover requested by `pendingOwner`. function completeOwnershipHandover(address pendingOwner) public payable virtual onlyOwner { /// @solidity memory-safe-assembly assembly { // Compute and set the handover slot to 0. mstore(0x0c, _HANDOVER_SLOT_SEED) mstore(0x00, pendingOwner) let handoverSlot := keccak256(0x0c, 0x20) // If the handover does not exist, or has expired. if gt(timestamp(), sload(handoverSlot)) { mstore(0x00, 0x6f5e8818) // `NoHandoverRequest()`. revert(0x1c, 0x04) } // Set the handover slot to 0. sstore(handoverSlot, 0) } _setOwner(pendingOwner); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PUBLIC READ FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the owner of the contract. function owner() public view virtual returns (address result) { /// @solidity memory-safe-assembly assembly { result := sload(_OWNER_SLOT) } } /// @dev Returns the expiry timestamp for the two-step ownership handover to `pendingOwner`. function ownershipHandoverExpiresAt(address pendingOwner) public view virtual returns (uint256 result) { /// @solidity memory-safe-assembly assembly { // Compute the handover slot. mstore(0x0c, _HANDOVER_SLOT_SEED) mstore(0x00, pendingOwner) // Load the handover slot. result := sload(keccak256(0x0c, 0x20)) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* MODIFIERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Marks a function as only callable by the owner. modifier onlyOwner() virtual { _checkOwner(); _; } }
// 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.23; interface IReverseRegistrar { function claim(address claimant) external; function setNameForAddr(address addr, address owner, address resolver, string memory name) external returns (bytes32); }
// 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 (last updated v5.0.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @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 IMulticallable { function multicall( bytes[] calldata data ) external returns (bytes[] memory results); function multicallWithNodeCheck( bytes32, bytes[] calldata data ) external returns (bytes[] memory results); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol) pragma solidity ^0.8.20; import {IERC165} from "./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); * } * ``` */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// 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 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); } unchecked { 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": [ "@ensdomains/buffer/=lib/buffer/", "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "buffer/=lib/buffer/contracts/", "ds-test/=lib/verifications/lib/forge-std/lib/ds-test/src/", "eas-contracts/=lib/eas-contracts/contracts/", "ens-contracts/=lib/ens-contracts/contracts/", "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", "forge-std/=lib/forge-std/src/", "openzeppelin-contracts-upgradeable/=lib/verifications/lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "openzeppelin/=lib/verifications/lib/openzeppelin-contracts-upgradeable/contracts/", "solady/=lib/solady/src/", "verifications/=lib/verifications/src/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "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":"contract ENS","name":"ens_","type":"address"},{"internalType":"address","name":"registrarController_","type":"address"},{"internalType":"address","name":"reverseRegistrar_","type":"address"},{"internalType":"address","name":"owner_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"CantSetSelfAsDelegate","type":"error"},{"inputs":[],"name":"CantSetSelfAsOperator","type":"error"},{"inputs":[],"name":"NewOwnerIsZeroAddress","type":"error"},{"inputs":[],"name":"NoHandoverRequest","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"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":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"address","name":"delegate","type":"address"},{"indexed":true,"internalType":"bool","name":"approved","type":"bool"}],"name":"Approved","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":"pendingOwner","type":"address"}],"name":"OwnershipHandoverCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","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":"address","name":"newRegistrarController","type":"address"}],"name":"RegistrarControllerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newReverseRegistrar","type":"address"}],"name":"ReverseRegistrarUpdated","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"},{"internalType":"address","name":"delegate","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cancelOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"clearRecords","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"completeOwnershipHandover","outputs":[],"stateMutability":"payable","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":[],"name":"ens","outputs":[{"internalType":"contract ENS","name":"","type":"address"}],"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":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"address","name":"delegate","type":"address"}],"name":"isApprovedFor","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"nodehash","type":"bytes32"},{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicallWithNodeCheck","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"nonpayable","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":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"ownershipHandoverExpiresAt","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"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":"registrarController","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"requestOwnershipHandover","outputs":[],"stateMutability":"payable","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":[],"name":"reverseRegistrar","outputs":[{"internalType":"address","name":"","type":"address"}],"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":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","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":"address","name":"registrarController_","type":"address"}],"name":"setRegistrarController","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"reverseRegistrar_","type":"address"}],"name":"setReverseRegistrar","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":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"zonehash","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60a06040523480156200001157600080fd5b50604051620034c7380380620034c783398101604081905262000034916200012e565b6001600160a01b03848116608052600b80546001600160a01b031990811686841617909155600c80549091169184169190911790556200007481620000db565b604051630f41a04d60e11b81526001600160a01b038281166004830152831690631e83409a90602401600060405180830381600087803b158015620000b857600080fd5b505af1158015620000cd573d6000803e3d6000fd5b505050505050505062000196565b6001600160a01b0316638b78c6d8198190558060007f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a35b50565b6001600160a01b03811681146200011557600080fd5b600080600080608085870312156200014557600080fd5b8451620001528162000118565b6020860151909450620001658162000118565b6040860151909350620001788162000118565b60608601519092506200018b8162000118565b939692955090935050565b60805161330e620001b9600039600081816103f80152611c69015261330e6000f3fe60806040526004361061025c5760003560e01c80638086985311610144578063ce3decdc116100b6578063e985e9c51161007a578063e985e9c5146107f9578063f04e283e14610842578063f1cb7e0614610855578063f2fde38b14610875578063f9cd32c514610888578063fee81cf4146108a857600080fd5b8063ce3decdc1461072b578063d5fa2b001461074b578063d700ff331461076b578063e32954eb146107b9578063e59d895d146107d957600080fd5b8063a4b91a0111610108578063a4b91a01146105e8578063a8fa568214610608578063a9784b3e14610628578063ac9650d814610679578063bc1c58d1146106a6578063c8690233146106c657600080fd5b8063808698531461054f5780638b95dd711461056f5780638da5cb5b1461058f5780639061b923146105a8578063a22cb465146105c857600080fd5b80633b3b57de116101dd57806359d1d43c116101a157806359d1d43c1461049a5780635c98042b146104c7578063623195b0146104e7578063691f343114610507578063715018a614610527578063773722131461052f57600080fd5b80633b3b57de146103c65780633f15457f146103e65780634cbf6ba41461041a57806354d1f13d14610472578063557499ba1461047a57600080fd5b80632569296211610224578063256929621461033e57806329448e1d1461034657806329cd62ea14610366578063304e6ade146103865780633603d758146103a657600080fd5b806301ffc9a7146102615780630af179d71461029657806310f13a8c146102b8578063124a319c146102d85780632203ab5614610310575b600080fd5b34801561026d57600080fd5b5061028161027c366004612790565b6108e9565b60405190151581526020015b60405180910390f35b3480156102a257600080fd5b506102b66102b13660046127ec565b610914565b005b3480156102c457600080fd5b506102b66102d3366004612837565b610b1d565b3480156102e457600080fd5b506102f86102f33660046128b0565b610be9565b6040516001600160a01b03909116815260200161028d565b34801561031c57600080fd5b5061033061032b3660046128dc565b610e3a565b60405161028d92919061294e565b6102b6610f70565b34801561035257600080fd5b506102b661036136600461297c565b610fbf565b34801561037257600080fd5b506102b6610381366004612999565b611011565b34801561039257600080fd5b506102b66103a13660046127ec565b6110ab565b3480156103b257600080fd5b506102b66103c13660046129c5565b611126565b3480156103d257600080fd5b506102f86103e13660046129c5565b6111c7565b3480156103f257600080fd5b506102f87f000000000000000000000000000000000000000000000000000000000000000081565b34801561042657600080fd5b506102816104353660046128dc565b600082815260208181526040808320546001600160401b031683526006825280832094835293815283822092825291909152205461ffff16151590565b6102b66111f9565b34801561048657600080fd5b506102b661049536600461297c565b611235565b3480156104a657600080fd5b506104ba6104b53660046127ec565b611287565b60405161028d91906129de565b3480156104d357600080fd5b506104ba6104e23660046129c5565b611366565b3480156104f357600080fd5b506102b66105023660046129f1565b611424565b34801561051357600080fd5b506104ba6105223660046129c5565b6114c0565b6102b66114f9565b34801561053b57600080fd5b506102b661054a3660046127ec565b61150d565b34801561055b57600080fd5b50600c546102f8906001600160a01b031681565b34801561057b57600080fd5b506102b661058a366004612ae5565b611588565b34801561059b57600080fd5b50638b78c6d819546102f8565b3480156105b457600080fd5b506104ba6105c3366004612b34565b611667565b3480156105d457600080fd5b506102b66105e3366004612ba7565b6116e0565b3480156105f457600080fd5b506102b6610603366004612bd3565b611775565b34801561061457600080fd5b506104ba610623366004612c11565b611813565b34801561063457600080fd5b50610281610643366004612c51565b6001600160a01b039283166000908152600e60209081526040808320948352938152838220929094168152925290205460ff1690565b34801561068557600080fd5b50610699610694366004612ccc565b611860565b60405161028d9190612d0d565b3480156106b257600080fd5b506104ba6106c13660046129c5565b61186e565b3480156106d257600080fd5b506107166106e13660046129c5565b600081815260208181526040808320546001600160401b03168352600982528083209383529290522080546001909101549091565b6040805192835260208301919091520161028d565b34801561073757600080fd5b506102b66107463660046127ec565b6118a7565b34801561075757600080fd5b506102b6610766366004612d71565b6119e8565b34801561077757600080fd5b506107a16107863660046129c5565b6000602081905290815260409020546001600160401b031681565b6040516001600160401b03909116815260200161028d565b3480156107c557600080fd5b506106996107d4366004612da1565b611a0f565b3480156107e557600080fd5b506102b66107f4366004612ddf565b611a24565b34801561080557600080fd5b50610281610814366004612e14565b6001600160a01b039182166000908152600d6020908152604080832093909416825291909152205460ff1690565b6102b661085036600461297c565b611aca565b34801561086157600080fd5b506104ba6108703660046128dc565b611b0a565b6102b661088336600461297c565b611bd1565b34801561089457600080fd5b50600b546102f8906001600160a01b031681565b3480156108b457600080fd5b506108db6108c336600461297c565b63389a75e1600c908152600091909152602090205490565b60405190815260200161028d565b60006001600160e01b03198216639061b92360e01b148061090e575061090e82611bf8565b92915050565b8261091e81611c1d565b61092757600080fd5b600084815260208181526040808320548151601f87018490048402810184019092528582528392606092839285926001600160401b0390911691839161098c9183918d908d90819084018382808284376000920191909152509293925050611d529050565b90505b80515160208201511015610ab6578661ffff166000036109f457806040015196506109b981611db3565b9450846040516020016109cc9190612e42565b6040516020818303038152906040528051906020012092506109ed81611dd4565b9350610aa8565b60006109ff82611db3565b9050816040015161ffff168861ffff16141580610a235750610a218682611df0565b155b15610aa657610a7f8c878a8e8e8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505060208801518d9150610a76908290612e74565b8b51158a611e0e565b816040015197508160200151965080955085805190602001209350610aa382611dd4565b94505b505b610ab181612075565b61098f565b50835115610b1157610b118a85888c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508c9250610b0891508290508f612e74565b89511588611e0e565b50505050505050505050565b84610b2781611c1d565b610b3057600080fd5b600086815260208181526040808320546001600160401b03168352600a825280832089845290915290819020905184918491610b6f9089908990612e87565b90815260200160405180910390209182610b8a929190612f21565b508484604051610b9b929190612e87565b6040518091039020867f448bc014f1536726cf8d54ff3d6481ed3cbc683c2591ca204274009afa09b1a187878787604051610bd99493929190613009565b60405180910390a3505050505050565b600082815260208181526040808320546001600160401b031683526007825280832085845282528083206001600160e01b0319851684529091528120546001600160a01b03168015610c3c57905061090e565b6000610c47856111c7565b90506001600160a01b038116610c625760009250505061090e565b6040516301ffc9a760e01b602482015260009081906001600160a01b0384169060440160408051601f198184030181529181526020820180516001600160e01b03166301ffc9a760e01b17905251610cba9190612e42565b600060405180830381855afa9150503d8060008114610cf5576040519150601f19603f3d011682016040523d82523d6000602084013e610cfa565b606091505b5091509150811580610d0d575060208151105b80610d37575080601f81518110610d2657610d2661303b565b01602001516001600160f81b031916155b15610d4957600094505050505061090e565b6040516001600160e01b0319871660248201526001600160a01b0384169060440160408051601f198184030181529181526020820180516001600160e01b03166301ffc9a760e01b17905251610d9f9190612e42565b600060405180830381855afa9150503d8060008114610dda576040519150601f19603f3d011682016040523d82523d6000602084013e610ddf565b606091505b509092509050811580610df3575060208151105b80610e1d575080601f81518110610e0c57610e0c61303b565b01602001516001600160f81b031916155b15610e2f57600094505050505061090e565b509095945050505050565b600082815260208181526040808320546001600160401b03168352600180835281842086855290925282206060915b848111610f505780851615801590610e99575060008181526020839052604081208054610e9590612e97565b9050115b15610f485780826000838152602001908152602001600020808054610ebd90612e97565b80601f0160208091040260200160405190810160405280929190818152602001828054610ee990612e97565b8015610f365780601f10610f0b57610100808354040283529160200191610f36565b820191906000526020600020905b815481529060010190602001808311610f1957829003601f168201915b50505050509050935093505050610f69565b60011b610e69565b5060006040518060200160405280600081525092509250505b9250929050565b60006202a3006001600160401b03164201905063389a75e1600c5233600052806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d600080a250565b610fc761215d565b600b80546001600160a01b0319166001600160a01b0383169081179091556040517f1877ffeba0b0229d8385c284d9b459f592be2d0f4acc2696fccfb0ae4b73b6b990600090a250565b8261101b81611c1d565b61102457600080fd5b60408051808201825284815260208082018581526000888152808352848120546001600160401b031681526009835284812089825283528490209251835551600190920191909155815185815290810184905285917f1d6f5e03d3f63eb58751986629a5439baee5079ff04f345becb66e23eb154e4691015b60405180910390a250505050565b826110b581611c1d565b6110be57600080fd5b600084815260208181526040808320546001600160401b031683526003825280832087845290915290206110f3838583612f21565b50837fe379c1624ed7e714cc0937528a32359d69d5281337765313dba4e081b72d7578848460405161109d929190613051565b8061113081611c1d565b61113957600080fd5b600082815260208190526040812080546001600160401b03169161115c83613065565b82546101009290920a6001600160401b03818102199093169183160217909155600084815260208181526040918290205491519190921681528492507fc6621ccb8f3f5a04bb6502154b2caf6adf5983fe76dfef1cfc9c42e3579db444910160405180910390a25050565b6000806111d583603c611b0a565b905080516000036111e95750600092915050565b6111f281612178565b9392505050565b63389a75e1600c523360005260006020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92600080a2565b61123d61215d565b600c80546001600160a01b0319166001600160a01b0383169081179091556040517fd192c0b229b00473ccb6ccfebf6642805bca1dcdf2d9fb4fd102c7dc7ea4ce2390600090a250565b600083815260208181526040808320546001600160401b03168352600a8252808320868452909152908190209051606091906112c69085908590612e87565b908152602001604051809103902080546112df90612e97565b80601f016020809104026020016040519081016040528092919081815260200182805461130b90612e97565b80156113585780601f1061132d57610100808354040283529160200191611358565b820191906000526020600020905b81548152906001019060200180831161133b57829003601f168201915b505050505090509392505050565b600081815260208181526040808320546001600160401b0316835260048252808320848452909152902080546060919061139f90612e97565b80601f01602080910402602001604051908101604052809291908181526020018280546113cb90612e97565b80156114185780601f106113ed57610100808354040283529160200191611418565b820191906000526020600020905b8154815290600101906020018083116113fb57829003601f168201915b50505050509050919050565b8361142e81611c1d565b61143757600080fd5b83611443600182612e74565b161561144e57600080fd5b600085815260208181526040808320546001600160401b03168352600182528083208884528252808320878452909152902061148b838583612f21565b50604051849086907faa121bbeef5f32f5961a2a28966e769023910fc9479059ee3495d4c1a696efe390600090a35050505050565b600081815260208181526040808320546001600160401b0316835260088252808320848452909152902080546060919061139f90612e97565b61150161215d565b61150b6000612197565b565b8261151781611c1d565b61152057600080fd5b600084815260208181526040808320546001600160401b03168352600882528083208784529091529020611555838583612f21565b50837fb7d29e911041e8d9b843369e890bcb72c9388692ba48b65ac54e7214c4c348f7848460405161109d929190613051565b8261159281611c1d565b61159b57600080fd5b837f65412581168e88a1e60c6459d7f44ae83ad0832e670826c05a4e2476b57af75284846040516115cd92919061294e565b60405180910390a2603c830361162457837f52d7d861f09ab3d26239d492e8968629f95e9e318cf0b73bfddc441522a15fd261160884612178565b6040516001600160a01b03909116815260200160405180910390a25b600084815260208181526040808320546001600160401b031683526002825280832087845282528083208684529091529020611660838261308b565b5050505050565b6060600080306001600160a01b0316846040516116849190612e42565b600060405180830381855afa9150503d80600081146116bf576040519150601f19603f3d011682016040523d82523d6000602084013e6116c4565b606091505b509150915081156116d857915061090e9050565b805160208201fd5b6001600160a01b03821633036117095760405163d4e4f6f360e01b815260040160405180910390fd5b336000818152600d602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6001600160a01b038216330361179e5760405163091db02f60e21b815260040160405180910390fd5b336000818152600e6020908152604080832087845282528083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519384529286917ff0ddb3b04746704017f9aa8bd728fcc2c1d11675041205350018915f5e4750a0910160405180910390a4505050565b600083815260208181526040808320546001600160401b03168352600582528083208684528252808320858452825280832061ffff8516845290915290208054606091906112df90612e97565b60606111f2600084846121d5565b600081815260208181526040808320546001600160401b0316835260038252808320848452909152902080546060919061139f90612e97565b826118b181611c1d565b6118ba57600080fd5b600084815260208181526040808320546001600160401b031680845260048352818420888552909252822080549192916118f390612e97565b80601f016020809104026020016040519081016040528092919081815260200182805461191f90612e97565b801561196c5780601f106119415761010080835404028352916020019161196c565b820191906000526020600020905b81548152906001019060200180831161194f57829003601f168201915b505050506001600160401b03841660009081526004602090815260408083208b845290915290209192506119a39050858783612f21565b50857f8f15ed4b723ef428f250961da8315675b507046737e19319fc1a4d81bfe87f858287876040516119d89392919061314a565b60405180910390a2505050505050565b816119f281611c1d565b6119fb57600080fd5b611a0a83603c61058a8561239d565b505050565b6060611a1c8484846121d5565b949350505050565b82611a2e81611c1d565b611a3757600080fd5b600084815260208181526040808320546001600160401b031683526007825280832087845282528083206001600160e01b031987168085529083529281902080546001600160a01b0319166001600160a01b038716908117909155905190815286917f7c69f06bea0bdef565b709e93a147836b0063ba2dd89f02d0b7e8d931e6a6daa910160405180910390a350505050565b611ad261215d565b63389a75e1600c52806000526020600c208054421115611afa57636f5e88186000526004601cfd5b60009055611b0781612197565b50565b600082815260208181526040808320546001600160401b031683526002825280832085845282528083208484529091529020805460609190611b4b90612e97565b80601f0160208091040260200160405190810160405280929190818152602001828054611b7790612e97565b8015611bc45780601f10611b9957610100808354040283529160200191611bc4565b820191906000526020600020905b815481529060010190602001808311611ba757829003601f168201915b5050505050905092915050565b611bd961215d565b8060601b611bef57637448fbae6000526004601cfd5b611b0781612197565b60006001600160e01b03198216631674750f60e21b148061090e575061090e826123cd565b600b546000906001600160a01b0316331480611c435750600c546001600160a01b031633145b15611c5057506001919050565b6040516302571be360e01b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906302571be390602401602060405180830381865afa158015611cb8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cdc919061317a565b90506001600160a01b038116331480611d1857506001600160a01b0381166000908152600d6020908152604080832033845290915290205460ff165b806111f257506001600160a01b0381166000908152600e60209081526040808320868452825280832033845290915290205460ff166111f2565b611da06040518060e001604052806060815260200160008152602001600061ffff168152602001600061ffff168152602001600063ffffffff16815260200160008152602001600081525090565b82815260c0810182905261090e81612075565b6020810151815160609161090e91611dcb90826123f2565b8451919061244c565b60a081015160c082015160609161090e91611dcb908290612e74565b6000815183511480156111f257506111f283600084600087516124c2565b865160208801206000611e2287878761244c565b90508315611f49576001600160401b03831660009081526005602090815260408083208d84528252808320858452825280832061ffff8c16845290915290208054611e6c90612e97565b159050611eca576001600160401b03831660009081526006602090815260408083208d845282528083208584529091528120805461ffff1691611eae83613197565b91906101000a81548161ffff021916908361ffff160217905550505b6001600160401b03831660009081526005602090815260408083208d84528252808320858452825280832061ffff8c1684529091528120611f0a91612725565b897f03528ed0c2a3ebc993b12ce3c16bb382f9c7d88ef7d8a1bf290eaf35955a12078a8a604051611f3c9291906131b5565b60405180910390a2610b11565b6001600160401b03831660009081526005602090815260408083208d84528252808320858452825280832061ffff8c16845290915290208054611f8b90612e97565b9050600003611feb576001600160401b03831660009081526006602090815260408083208d845282528083208584529091528120805461ffff1691611fcf836131db565b91906101000a81548161ffff021916908361ffff160217905550505b6001600160401b03831660009081526005602090815260408083208d84528252808320858452825280832061ffff8c168452909152902061202c828261308b565b50897f52a608b3303a48862d07a73d82fa221318c0027fbbcfb1b2329bface3f19ff2b8a8a84604051612061939291906131f2565b60405180910390a250505050505050505050565b60c0810151602082018190528151511161208c5750565b60006120a0826000015183602001516123f2565b82602001516120af9190613221565b82519091506120be90826124e5565b61ffff1660408301526120d2600282613221565b82519091506120e190826124e5565b61ffff1660608301526120f5600282613221565b8251909150612104908261250d565b63ffffffff16608083015261211a600482613221565b825190915060009061212c90836124e5565b61ffff16905061213d600283613221565b60a0840181905291506121508183613221565b60c0909301929092525050565b638b78c6d81954331461150b576382b429006000526004601cfd5b6000815160141461218857600080fd5b5060200151600160601b900490565b638b78c6d81980546001600160a01b039092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a355565b6060816001600160401b038111156121ef576121ef612a43565b60405190808252806020026020018201604052801561222257816020015b606081526020019060019003908161220d5790505b50905060005b828110156123955784156122e857600084848381811061224a5761224a61303b565b905060200281019061225c9190613234565b61226b9160249160049161327a565b612274916132a4565b90508581146122e65760405162461bcd60e51b815260206004820152603460248201527f6d756c746963616c6c3a20416c6c207265636f726473206d7573742068617665604482015273040c240dac2e8c6d0d2dcce40dcc2dacad0c2e6d60631b606482015260840160405180910390fd5b505b600080308686858181106122fe576122fe61303b565b90506020028101906123109190613234565b60405161231e929190612e87565b600060405180830381855af49150503d8060008114612359576040519150601f19603f3d011682016040523d82523d6000602084013e61235e565b606091505b50915091508161236d57600080fd5b808484815181106123805761238061303b565b60209081029190910101525050600101612228565b509392505050565b604080516014808252818301909252606091602082018180368337505050600160601b9290920260208301525090565b60006001600160e01b0319821663c869023360e01b148061090e575061090e82612537565b6000815b83518110612406576124066132c2565b6000612412858361255c565b60ff169050612422816001613221565b61242c9083613221565b91508060000361243c5750612442565b506123f6565b611a1c8382612e74565b825160609061245b8385613221565b111561246657600080fd5b6000826001600160401b0381111561248057612480612a43565b6040519080825280601f01601f1916602001820160405280156124aa576020820181803683370190505b50905060208082019086860101610e2f828287612580565b60006124cf8484846125d6565b6124da8787856125d6565b149695505050505050565b81516000906124f5836002613221565b111561250057600080fd5b50016002015161ffff1690565b815160009061251d836004613221565b111561252857600080fd5b50016004015163ffffffff1690565b60006001600160e01b0319821663691f343160e01b148061090e575061090e826125fa565b60008282815181106125705761257061303b565b016020015160f81c905092915050565b602081106125b85781518352612597602084613221565b92506125a4602083613221565b91506125b1602082612e74565b9050612580565b905182516020929092036101000a6000190180199091169116179052565b82516000906125e58385613221565b11156125f057600080fd5b5091016020012090565b60006001600160e01b031982166304928c6760e21b148061090e575061090e8260006001600160e01b0319821663547d2b4160e11b148061264b57506001600160e01b03198216635c98042b60e01b145b8061090e575061090e8260006001600160e01b0319821663bc1c58d160e01b148061090e575061090e8260006001600160e01b03198216631d9dabef60e11b14806126a657506001600160e01b031982166378e5bf0360e11b145b8061090e575061090e8260006001600160e01b03198216631101d5ab60e11b148061090e575061090e8260006001600160e01b0319821663d700ff3360e01b148061090e575061090e8260006001600160e01b03198216634fbf043360e01b148061090e57506301ffc9a760e01b6001600160e01b031983161461090e565b50805461273190612e97565b6000825580601f10612741575050565b601f016020900490600052602060002090810190611b0791905b8082111561276f576000815560010161275b565b5090565b80356001600160e01b03198116811461278b57600080fd5b919050565b6000602082840312156127a257600080fd5b6111f282612773565b60008083601f8401126127bd57600080fd5b5081356001600160401b038111156127d457600080fd5b602083019150836020828501011115610f6957600080fd5b60008060006040848603121561280157600080fd5b8335925060208401356001600160401b0381111561281e57600080fd5b61282a868287016127ab565b9497909650939450505050565b60008060008060006060868803121561284f57600080fd5b8535945060208601356001600160401b038082111561286d57600080fd5b61287989838a016127ab565b9096509450604088013591508082111561289257600080fd5b5061289f888289016127ab565b969995985093965092949392505050565b600080604083850312156128c357600080fd5b823591506128d360208401612773565b90509250929050565b600080604083850312156128ef57600080fd5b50508035926020909101359150565b60005b83811015612919578181015183820152602001612901565b50506000910152565b6000815180845261293a8160208601602086016128fe565b601f01601f19169290920160200192915050565b828152604060208201526000611a1c6040830184612922565b6001600160a01b0381168114611b0757600080fd5b60006020828403121561298e57600080fd5b81356111f281612967565b6000806000606084860312156129ae57600080fd5b505081359360208301359350604090920135919050565b6000602082840312156129d757600080fd5b5035919050565b6020815260006111f26020830184612922565b60008060008060608587031215612a0757600080fd5b843593506020850135925060408501356001600160401b03811115612a2b57600080fd5b612a37878288016127ab565b95989497509550505050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112612a6a57600080fd5b81356001600160401b0380821115612a8457612a84612a43565b604051601f8301601f19908116603f01168101908282118183101715612aac57612aac612a43565b81604052838152866020858801011115612ac557600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600060608486031215612afa57600080fd5b833592506020840135915060408401356001600160401b03811115612b1e57600080fd5b612b2a86828701612a59565b9150509250925092565b60008060408385031215612b4757600080fd5b82356001600160401b0380821115612b5e57600080fd5b612b6a86838701612a59565b93506020850135915080821115612b8057600080fd5b50612b8d85828601612a59565b9150509250929050565b8035801515811461278b57600080fd5b60008060408385031215612bba57600080fd5b8235612bc581612967565b91506128d360208401612b97565b600080600060608486031215612be857600080fd5b833592506020840135612bfa81612967565b9150612c0860408501612b97565b90509250925092565b600080600060608486031215612c2657600080fd5b8335925060208401359150604084013561ffff81168114612c4657600080fd5b809150509250925092565b600080600060608486031215612c6657600080fd5b8335612c7181612967565b9250602084013591506040840135612c4681612967565b60008083601f840112612c9a57600080fd5b5081356001600160401b03811115612cb157600080fd5b6020830191508360208260051b8501011115610f6957600080fd5b60008060208385031215612cdf57600080fd5b82356001600160401b03811115612cf557600080fd5b612d0185828601612c88565b90969095509350505050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b82811015612d6457603f19888603018452612d52858351612922565b94509285019290850190600101612d36565b5092979650505050505050565b60008060408385031215612d8457600080fd5b823591506020830135612d9681612967565b809150509250929050565b600080600060408486031215612db657600080fd5b8335925060208401356001600160401b03811115612dd357600080fd5b61282a86828701612c88565b600080600060608486031215612df457600080fd5b83359250612e0460208501612773565b91506040840135612c4681612967565b60008060408385031215612e2757600080fd5b8235612e3281612967565b91506020830135612d9681612967565b60008251612e548184602087016128fe565b9190910192915050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561090e5761090e612e5e565b8183823760009101908152919050565b600181811c90821680612eab57607f821691505b602082108103612ecb57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115611a0a576000816000526020600020601f850160051c81016020861015612efa5750805b601f850160051c820191505b81811015612f1957828155600101612f06565b505050505050565b6001600160401b03831115612f3857612f38612a43565b612f4c83612f468354612e97565b83612ed1565b6000601f841160018114612f805760008515612f685750838201355b600019600387901b1c1916600186901b178355611660565b600083815260209020601f19861690835b82811015612fb15786850135825560209485019460019092019101612f91565b5086821015612fce5760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60408152600061301d604083018688612fe0565b8281036020840152613030818587612fe0565b979650505050505050565b634e487b7160e01b600052603260045260246000fd5b602081526000611a1c602083018486612fe0565b60006001600160401b0380831681810361308157613081612e5e565b6001019392505050565b81516001600160401b038111156130a4576130a4612a43565b6130b8816130b28454612e97565b84612ed1565b602080601f8311600181146130ed57600084156130d55750858301515b600019600386901b1c1916600185901b178555612f19565b600085815260208120601f198616915b8281101561311c578886015182559484019460019091019084016130fd565b508582101561313a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60408152600061315d6040830186612922565b8281036020840152613170818587612fe0565b9695505050505050565b60006020828403121561318c57600080fd5b81516111f281612967565b600061ffff8216806131ab576131ab612e5e565b6000190192915050565b6040815260006131c86040830185612922565b905061ffff831660208301529392505050565b600061ffff80831681810361308157613081612e5e565b6060815260006132056060830186612922565b61ffff8516602084015282810360408401526131708185612922565b8082018082111561090e5761090e612e5e565b6000808335601e1984360301811261324b57600080fd5b8301803591506001600160401b0382111561326557600080fd5b602001915036819003821315610f6957600080fd5b6000808585111561328a57600080fd5b8386111561329757600080fd5b5050820193919092039150565b8035602083101561090e57600019602084900360031b1b1692915050565b634e487b7160e01b600052600160045260246000fdfea26469706673582212208c1875cb11c4334d4d7f887f78c9588d805d170d1be332093828d3e32268139964736f6c63430008170033000000000000000000000000b94704422c2a1e396835a571837aa5ae53285a95000000000000000000000000d3e6775ed9b7dc12b205c8e608dc3767b9e5efda00000000000000000000000079ea96012eea67a83431f1701b3dff7e37f9e282000000000000000000000000f9bba2f07a2c95fc4225f1caec76e6bf04b463e9
Deployed Bytecode
0x60806040526004361061025c5760003560e01c80638086985311610144578063ce3decdc116100b6578063e985e9c51161007a578063e985e9c5146107f9578063f04e283e14610842578063f1cb7e0614610855578063f2fde38b14610875578063f9cd32c514610888578063fee81cf4146108a857600080fd5b8063ce3decdc1461072b578063d5fa2b001461074b578063d700ff331461076b578063e32954eb146107b9578063e59d895d146107d957600080fd5b8063a4b91a0111610108578063a4b91a01146105e8578063a8fa568214610608578063a9784b3e14610628578063ac9650d814610679578063bc1c58d1146106a6578063c8690233146106c657600080fd5b8063808698531461054f5780638b95dd711461056f5780638da5cb5b1461058f5780639061b923146105a8578063a22cb465146105c857600080fd5b80633b3b57de116101dd57806359d1d43c116101a157806359d1d43c1461049a5780635c98042b146104c7578063623195b0146104e7578063691f343114610507578063715018a614610527578063773722131461052f57600080fd5b80633b3b57de146103c65780633f15457f146103e65780634cbf6ba41461041a57806354d1f13d14610472578063557499ba1461047a57600080fd5b80632569296211610224578063256929621461033e57806329448e1d1461034657806329cd62ea14610366578063304e6ade146103865780633603d758146103a657600080fd5b806301ffc9a7146102615780630af179d71461029657806310f13a8c146102b8578063124a319c146102d85780632203ab5614610310575b600080fd5b34801561026d57600080fd5b5061028161027c366004612790565b6108e9565b60405190151581526020015b60405180910390f35b3480156102a257600080fd5b506102b66102b13660046127ec565b610914565b005b3480156102c457600080fd5b506102b66102d3366004612837565b610b1d565b3480156102e457600080fd5b506102f86102f33660046128b0565b610be9565b6040516001600160a01b03909116815260200161028d565b34801561031c57600080fd5b5061033061032b3660046128dc565b610e3a565b60405161028d92919061294e565b6102b6610f70565b34801561035257600080fd5b506102b661036136600461297c565b610fbf565b34801561037257600080fd5b506102b6610381366004612999565b611011565b34801561039257600080fd5b506102b66103a13660046127ec565b6110ab565b3480156103b257600080fd5b506102b66103c13660046129c5565b611126565b3480156103d257600080fd5b506102f86103e13660046129c5565b6111c7565b3480156103f257600080fd5b506102f87f000000000000000000000000b94704422c2a1e396835a571837aa5ae53285a9581565b34801561042657600080fd5b506102816104353660046128dc565b600082815260208181526040808320546001600160401b031683526006825280832094835293815283822092825291909152205461ffff16151590565b6102b66111f9565b34801561048657600080fd5b506102b661049536600461297c565b611235565b3480156104a657600080fd5b506104ba6104b53660046127ec565b611287565b60405161028d91906129de565b3480156104d357600080fd5b506104ba6104e23660046129c5565b611366565b3480156104f357600080fd5b506102b66105023660046129f1565b611424565b34801561051357600080fd5b506104ba6105223660046129c5565b6114c0565b6102b66114f9565b34801561053b57600080fd5b506102b661054a3660046127ec565b61150d565b34801561055b57600080fd5b50600c546102f8906001600160a01b031681565b34801561057b57600080fd5b506102b661058a366004612ae5565b611588565b34801561059b57600080fd5b50638b78c6d819546102f8565b3480156105b457600080fd5b506104ba6105c3366004612b34565b611667565b3480156105d457600080fd5b506102b66105e3366004612ba7565b6116e0565b3480156105f457600080fd5b506102b6610603366004612bd3565b611775565b34801561061457600080fd5b506104ba610623366004612c11565b611813565b34801561063457600080fd5b50610281610643366004612c51565b6001600160a01b039283166000908152600e60209081526040808320948352938152838220929094168152925290205460ff1690565b34801561068557600080fd5b50610699610694366004612ccc565b611860565b60405161028d9190612d0d565b3480156106b257600080fd5b506104ba6106c13660046129c5565b61186e565b3480156106d257600080fd5b506107166106e13660046129c5565b600081815260208181526040808320546001600160401b03168352600982528083209383529290522080546001909101549091565b6040805192835260208301919091520161028d565b34801561073757600080fd5b506102b66107463660046127ec565b6118a7565b34801561075757600080fd5b506102b6610766366004612d71565b6119e8565b34801561077757600080fd5b506107a16107863660046129c5565b6000602081905290815260409020546001600160401b031681565b6040516001600160401b03909116815260200161028d565b3480156107c557600080fd5b506106996107d4366004612da1565b611a0f565b3480156107e557600080fd5b506102b66107f4366004612ddf565b611a24565b34801561080557600080fd5b50610281610814366004612e14565b6001600160a01b039182166000908152600d6020908152604080832093909416825291909152205460ff1690565b6102b661085036600461297c565b611aca565b34801561086157600080fd5b506104ba6108703660046128dc565b611b0a565b6102b661088336600461297c565b611bd1565b34801561089457600080fd5b50600b546102f8906001600160a01b031681565b3480156108b457600080fd5b506108db6108c336600461297c565b63389a75e1600c908152600091909152602090205490565b60405190815260200161028d565b60006001600160e01b03198216639061b92360e01b148061090e575061090e82611bf8565b92915050565b8261091e81611c1d565b61092757600080fd5b600084815260208181526040808320548151601f87018490048402810184019092528582528392606092839285926001600160401b0390911691839161098c9183918d908d90819084018382808284376000920191909152509293925050611d529050565b90505b80515160208201511015610ab6578661ffff166000036109f457806040015196506109b981611db3565b9450846040516020016109cc9190612e42565b6040516020818303038152906040528051906020012092506109ed81611dd4565b9350610aa8565b60006109ff82611db3565b9050816040015161ffff168861ffff16141580610a235750610a218682611df0565b155b15610aa657610a7f8c878a8e8e8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505060208801518d9150610a76908290612e74565b8b51158a611e0e565b816040015197508160200151965080955085805190602001209350610aa382611dd4565b94505b505b610ab181612075565b61098f565b50835115610b1157610b118a85888c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508c9250610b0891508290508f612e74565b89511588611e0e565b50505050505050505050565b84610b2781611c1d565b610b3057600080fd5b600086815260208181526040808320546001600160401b03168352600a825280832089845290915290819020905184918491610b6f9089908990612e87565b90815260200160405180910390209182610b8a929190612f21565b508484604051610b9b929190612e87565b6040518091039020867f448bc014f1536726cf8d54ff3d6481ed3cbc683c2591ca204274009afa09b1a187878787604051610bd99493929190613009565b60405180910390a3505050505050565b600082815260208181526040808320546001600160401b031683526007825280832085845282528083206001600160e01b0319851684529091528120546001600160a01b03168015610c3c57905061090e565b6000610c47856111c7565b90506001600160a01b038116610c625760009250505061090e565b6040516301ffc9a760e01b602482015260009081906001600160a01b0384169060440160408051601f198184030181529181526020820180516001600160e01b03166301ffc9a760e01b17905251610cba9190612e42565b600060405180830381855afa9150503d8060008114610cf5576040519150601f19603f3d011682016040523d82523d6000602084013e610cfa565b606091505b5091509150811580610d0d575060208151105b80610d37575080601f81518110610d2657610d2661303b565b01602001516001600160f81b031916155b15610d4957600094505050505061090e565b6040516001600160e01b0319871660248201526001600160a01b0384169060440160408051601f198184030181529181526020820180516001600160e01b03166301ffc9a760e01b17905251610d9f9190612e42565b600060405180830381855afa9150503d8060008114610dda576040519150601f19603f3d011682016040523d82523d6000602084013e610ddf565b606091505b509092509050811580610df3575060208151105b80610e1d575080601f81518110610e0c57610e0c61303b565b01602001516001600160f81b031916155b15610e2f57600094505050505061090e565b509095945050505050565b600082815260208181526040808320546001600160401b03168352600180835281842086855290925282206060915b848111610f505780851615801590610e99575060008181526020839052604081208054610e9590612e97565b9050115b15610f485780826000838152602001908152602001600020808054610ebd90612e97565b80601f0160208091040260200160405190810160405280929190818152602001828054610ee990612e97565b8015610f365780601f10610f0b57610100808354040283529160200191610f36565b820191906000526020600020905b815481529060010190602001808311610f1957829003601f168201915b50505050509050935093505050610f69565b60011b610e69565b5060006040518060200160405280600081525092509250505b9250929050565b60006202a3006001600160401b03164201905063389a75e1600c5233600052806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d600080a250565b610fc761215d565b600b80546001600160a01b0319166001600160a01b0383169081179091556040517f1877ffeba0b0229d8385c284d9b459f592be2d0f4acc2696fccfb0ae4b73b6b990600090a250565b8261101b81611c1d565b61102457600080fd5b60408051808201825284815260208082018581526000888152808352848120546001600160401b031681526009835284812089825283528490209251835551600190920191909155815185815290810184905285917f1d6f5e03d3f63eb58751986629a5439baee5079ff04f345becb66e23eb154e4691015b60405180910390a250505050565b826110b581611c1d565b6110be57600080fd5b600084815260208181526040808320546001600160401b031683526003825280832087845290915290206110f3838583612f21565b50837fe379c1624ed7e714cc0937528a32359d69d5281337765313dba4e081b72d7578848460405161109d929190613051565b8061113081611c1d565b61113957600080fd5b600082815260208190526040812080546001600160401b03169161115c83613065565b82546101009290920a6001600160401b03818102199093169183160217909155600084815260208181526040918290205491519190921681528492507fc6621ccb8f3f5a04bb6502154b2caf6adf5983fe76dfef1cfc9c42e3579db444910160405180910390a25050565b6000806111d583603c611b0a565b905080516000036111e95750600092915050565b6111f281612178565b9392505050565b63389a75e1600c523360005260006020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92600080a2565b61123d61215d565b600c80546001600160a01b0319166001600160a01b0383169081179091556040517fd192c0b229b00473ccb6ccfebf6642805bca1dcdf2d9fb4fd102c7dc7ea4ce2390600090a250565b600083815260208181526040808320546001600160401b03168352600a8252808320868452909152908190209051606091906112c69085908590612e87565b908152602001604051809103902080546112df90612e97565b80601f016020809104026020016040519081016040528092919081815260200182805461130b90612e97565b80156113585780601f1061132d57610100808354040283529160200191611358565b820191906000526020600020905b81548152906001019060200180831161133b57829003601f168201915b505050505090509392505050565b600081815260208181526040808320546001600160401b0316835260048252808320848452909152902080546060919061139f90612e97565b80601f01602080910402602001604051908101604052809291908181526020018280546113cb90612e97565b80156114185780601f106113ed57610100808354040283529160200191611418565b820191906000526020600020905b8154815290600101906020018083116113fb57829003601f168201915b50505050509050919050565b8361142e81611c1d565b61143757600080fd5b83611443600182612e74565b161561144e57600080fd5b600085815260208181526040808320546001600160401b03168352600182528083208884528252808320878452909152902061148b838583612f21565b50604051849086907faa121bbeef5f32f5961a2a28966e769023910fc9479059ee3495d4c1a696efe390600090a35050505050565b600081815260208181526040808320546001600160401b0316835260088252808320848452909152902080546060919061139f90612e97565b61150161215d565b61150b6000612197565b565b8261151781611c1d565b61152057600080fd5b600084815260208181526040808320546001600160401b03168352600882528083208784529091529020611555838583612f21565b50837fb7d29e911041e8d9b843369e890bcb72c9388692ba48b65ac54e7214c4c348f7848460405161109d929190613051565b8261159281611c1d565b61159b57600080fd5b837f65412581168e88a1e60c6459d7f44ae83ad0832e670826c05a4e2476b57af75284846040516115cd92919061294e565b60405180910390a2603c830361162457837f52d7d861f09ab3d26239d492e8968629f95e9e318cf0b73bfddc441522a15fd261160884612178565b6040516001600160a01b03909116815260200160405180910390a25b600084815260208181526040808320546001600160401b031683526002825280832087845282528083208684529091529020611660838261308b565b5050505050565b6060600080306001600160a01b0316846040516116849190612e42565b600060405180830381855afa9150503d80600081146116bf576040519150601f19603f3d011682016040523d82523d6000602084013e6116c4565b606091505b509150915081156116d857915061090e9050565b805160208201fd5b6001600160a01b03821633036117095760405163d4e4f6f360e01b815260040160405180910390fd5b336000818152600d602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6001600160a01b038216330361179e5760405163091db02f60e21b815260040160405180910390fd5b336000818152600e6020908152604080832087845282528083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519384529286917ff0ddb3b04746704017f9aa8bd728fcc2c1d11675041205350018915f5e4750a0910160405180910390a4505050565b600083815260208181526040808320546001600160401b03168352600582528083208684528252808320858452825280832061ffff8516845290915290208054606091906112df90612e97565b60606111f2600084846121d5565b600081815260208181526040808320546001600160401b0316835260038252808320848452909152902080546060919061139f90612e97565b826118b181611c1d565b6118ba57600080fd5b600084815260208181526040808320546001600160401b031680845260048352818420888552909252822080549192916118f390612e97565b80601f016020809104026020016040519081016040528092919081815260200182805461191f90612e97565b801561196c5780601f106119415761010080835404028352916020019161196c565b820191906000526020600020905b81548152906001019060200180831161194f57829003601f168201915b505050506001600160401b03841660009081526004602090815260408083208b845290915290209192506119a39050858783612f21565b50857f8f15ed4b723ef428f250961da8315675b507046737e19319fc1a4d81bfe87f858287876040516119d89392919061314a565b60405180910390a2505050505050565b816119f281611c1d565b6119fb57600080fd5b611a0a83603c61058a8561239d565b505050565b6060611a1c8484846121d5565b949350505050565b82611a2e81611c1d565b611a3757600080fd5b600084815260208181526040808320546001600160401b031683526007825280832087845282528083206001600160e01b031987168085529083529281902080546001600160a01b0319166001600160a01b038716908117909155905190815286917f7c69f06bea0bdef565b709e93a147836b0063ba2dd89f02d0b7e8d931e6a6daa910160405180910390a350505050565b611ad261215d565b63389a75e1600c52806000526020600c208054421115611afa57636f5e88186000526004601cfd5b60009055611b0781612197565b50565b600082815260208181526040808320546001600160401b031683526002825280832085845282528083208484529091529020805460609190611b4b90612e97565b80601f0160208091040260200160405190810160405280929190818152602001828054611b7790612e97565b8015611bc45780601f10611b9957610100808354040283529160200191611bc4565b820191906000526020600020905b815481529060010190602001808311611ba757829003601f168201915b5050505050905092915050565b611bd961215d565b8060601b611bef57637448fbae6000526004601cfd5b611b0781612197565b60006001600160e01b03198216631674750f60e21b148061090e575061090e826123cd565b600b546000906001600160a01b0316331480611c435750600c546001600160a01b031633145b15611c5057506001919050565b6040516302571be360e01b8152600481018390526000907f000000000000000000000000b94704422c2a1e396835a571837aa5ae53285a956001600160a01b0316906302571be390602401602060405180830381865afa158015611cb8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cdc919061317a565b90506001600160a01b038116331480611d1857506001600160a01b0381166000908152600d6020908152604080832033845290915290205460ff165b806111f257506001600160a01b0381166000908152600e60209081526040808320868452825280832033845290915290205460ff166111f2565b611da06040518060e001604052806060815260200160008152602001600061ffff168152602001600061ffff168152602001600063ffffffff16815260200160008152602001600081525090565b82815260c0810182905261090e81612075565b6020810151815160609161090e91611dcb90826123f2565b8451919061244c565b60a081015160c082015160609161090e91611dcb908290612e74565b6000815183511480156111f257506111f283600084600087516124c2565b865160208801206000611e2287878761244c565b90508315611f49576001600160401b03831660009081526005602090815260408083208d84528252808320858452825280832061ffff8c16845290915290208054611e6c90612e97565b159050611eca576001600160401b03831660009081526006602090815260408083208d845282528083208584529091528120805461ffff1691611eae83613197565b91906101000a81548161ffff021916908361ffff160217905550505b6001600160401b03831660009081526005602090815260408083208d84528252808320858452825280832061ffff8c1684529091528120611f0a91612725565b897f03528ed0c2a3ebc993b12ce3c16bb382f9c7d88ef7d8a1bf290eaf35955a12078a8a604051611f3c9291906131b5565b60405180910390a2610b11565b6001600160401b03831660009081526005602090815260408083208d84528252808320858452825280832061ffff8c16845290915290208054611f8b90612e97565b9050600003611feb576001600160401b03831660009081526006602090815260408083208d845282528083208584529091528120805461ffff1691611fcf836131db565b91906101000a81548161ffff021916908361ffff160217905550505b6001600160401b03831660009081526005602090815260408083208d84528252808320858452825280832061ffff8c168452909152902061202c828261308b565b50897f52a608b3303a48862d07a73d82fa221318c0027fbbcfb1b2329bface3f19ff2b8a8a84604051612061939291906131f2565b60405180910390a250505050505050505050565b60c0810151602082018190528151511161208c5750565b60006120a0826000015183602001516123f2565b82602001516120af9190613221565b82519091506120be90826124e5565b61ffff1660408301526120d2600282613221565b82519091506120e190826124e5565b61ffff1660608301526120f5600282613221565b8251909150612104908261250d565b63ffffffff16608083015261211a600482613221565b825190915060009061212c90836124e5565b61ffff16905061213d600283613221565b60a0840181905291506121508183613221565b60c0909301929092525050565b638b78c6d81954331461150b576382b429006000526004601cfd5b6000815160141461218857600080fd5b5060200151600160601b900490565b638b78c6d81980546001600160a01b039092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a355565b6060816001600160401b038111156121ef576121ef612a43565b60405190808252806020026020018201604052801561222257816020015b606081526020019060019003908161220d5790505b50905060005b828110156123955784156122e857600084848381811061224a5761224a61303b565b905060200281019061225c9190613234565b61226b9160249160049161327a565b612274916132a4565b90508581146122e65760405162461bcd60e51b815260206004820152603460248201527f6d756c746963616c6c3a20416c6c207265636f726473206d7573742068617665604482015273040c240dac2e8c6d0d2dcce40dcc2dacad0c2e6d60631b606482015260840160405180910390fd5b505b600080308686858181106122fe576122fe61303b565b90506020028101906123109190613234565b60405161231e929190612e87565b600060405180830381855af49150503d8060008114612359576040519150601f19603f3d011682016040523d82523d6000602084013e61235e565b606091505b50915091508161236d57600080fd5b808484815181106123805761238061303b565b60209081029190910101525050600101612228565b509392505050565b604080516014808252818301909252606091602082018180368337505050600160601b9290920260208301525090565b60006001600160e01b0319821663c869023360e01b148061090e575061090e82612537565b6000815b83518110612406576124066132c2565b6000612412858361255c565b60ff169050612422816001613221565b61242c9083613221565b91508060000361243c5750612442565b506123f6565b611a1c8382612e74565b825160609061245b8385613221565b111561246657600080fd5b6000826001600160401b0381111561248057612480612a43565b6040519080825280601f01601f1916602001820160405280156124aa576020820181803683370190505b50905060208082019086860101610e2f828287612580565b60006124cf8484846125d6565b6124da8787856125d6565b149695505050505050565b81516000906124f5836002613221565b111561250057600080fd5b50016002015161ffff1690565b815160009061251d836004613221565b111561252857600080fd5b50016004015163ffffffff1690565b60006001600160e01b0319821663691f343160e01b148061090e575061090e826125fa565b60008282815181106125705761257061303b565b016020015160f81c905092915050565b602081106125b85781518352612597602084613221565b92506125a4602083613221565b91506125b1602082612e74565b9050612580565b905182516020929092036101000a6000190180199091169116179052565b82516000906125e58385613221565b11156125f057600080fd5b5091016020012090565b60006001600160e01b031982166304928c6760e21b148061090e575061090e8260006001600160e01b0319821663547d2b4160e11b148061264b57506001600160e01b03198216635c98042b60e01b145b8061090e575061090e8260006001600160e01b0319821663bc1c58d160e01b148061090e575061090e8260006001600160e01b03198216631d9dabef60e11b14806126a657506001600160e01b031982166378e5bf0360e11b145b8061090e575061090e8260006001600160e01b03198216631101d5ab60e11b148061090e575061090e8260006001600160e01b0319821663d700ff3360e01b148061090e575061090e8260006001600160e01b03198216634fbf043360e01b148061090e57506301ffc9a760e01b6001600160e01b031983161461090e565b50805461273190612e97565b6000825580601f10612741575050565b601f016020900490600052602060002090810190611b0791905b8082111561276f576000815560010161275b565b5090565b80356001600160e01b03198116811461278b57600080fd5b919050565b6000602082840312156127a257600080fd5b6111f282612773565b60008083601f8401126127bd57600080fd5b5081356001600160401b038111156127d457600080fd5b602083019150836020828501011115610f6957600080fd5b60008060006040848603121561280157600080fd5b8335925060208401356001600160401b0381111561281e57600080fd5b61282a868287016127ab565b9497909650939450505050565b60008060008060006060868803121561284f57600080fd5b8535945060208601356001600160401b038082111561286d57600080fd5b61287989838a016127ab565b9096509450604088013591508082111561289257600080fd5b5061289f888289016127ab565b969995985093965092949392505050565b600080604083850312156128c357600080fd5b823591506128d360208401612773565b90509250929050565b600080604083850312156128ef57600080fd5b50508035926020909101359150565b60005b83811015612919578181015183820152602001612901565b50506000910152565b6000815180845261293a8160208601602086016128fe565b601f01601f19169290920160200192915050565b828152604060208201526000611a1c6040830184612922565b6001600160a01b0381168114611b0757600080fd5b60006020828403121561298e57600080fd5b81356111f281612967565b6000806000606084860312156129ae57600080fd5b505081359360208301359350604090920135919050565b6000602082840312156129d757600080fd5b5035919050565b6020815260006111f26020830184612922565b60008060008060608587031215612a0757600080fd5b843593506020850135925060408501356001600160401b03811115612a2b57600080fd5b612a37878288016127ab565b95989497509550505050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112612a6a57600080fd5b81356001600160401b0380821115612a8457612a84612a43565b604051601f8301601f19908116603f01168101908282118183101715612aac57612aac612a43565b81604052838152866020858801011115612ac557600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600060608486031215612afa57600080fd5b833592506020840135915060408401356001600160401b03811115612b1e57600080fd5b612b2a86828701612a59565b9150509250925092565b60008060408385031215612b4757600080fd5b82356001600160401b0380821115612b5e57600080fd5b612b6a86838701612a59565b93506020850135915080821115612b8057600080fd5b50612b8d85828601612a59565b9150509250929050565b8035801515811461278b57600080fd5b60008060408385031215612bba57600080fd5b8235612bc581612967565b91506128d360208401612b97565b600080600060608486031215612be857600080fd5b833592506020840135612bfa81612967565b9150612c0860408501612b97565b90509250925092565b600080600060608486031215612c2657600080fd5b8335925060208401359150604084013561ffff81168114612c4657600080fd5b809150509250925092565b600080600060608486031215612c6657600080fd5b8335612c7181612967565b9250602084013591506040840135612c4681612967565b60008083601f840112612c9a57600080fd5b5081356001600160401b03811115612cb157600080fd5b6020830191508360208260051b8501011115610f6957600080fd5b60008060208385031215612cdf57600080fd5b82356001600160401b03811115612cf557600080fd5b612d0185828601612c88565b90969095509350505050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b82811015612d6457603f19888603018452612d52858351612922565b94509285019290850190600101612d36565b5092979650505050505050565b60008060408385031215612d8457600080fd5b823591506020830135612d9681612967565b809150509250929050565b600080600060408486031215612db657600080fd5b8335925060208401356001600160401b03811115612dd357600080fd5b61282a86828701612c88565b600080600060608486031215612df457600080fd5b83359250612e0460208501612773565b91506040840135612c4681612967565b60008060408385031215612e2757600080fd5b8235612e3281612967565b91506020830135612d9681612967565b60008251612e548184602087016128fe565b9190910192915050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561090e5761090e612e5e565b8183823760009101908152919050565b600181811c90821680612eab57607f821691505b602082108103612ecb57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115611a0a576000816000526020600020601f850160051c81016020861015612efa5750805b601f850160051c820191505b81811015612f1957828155600101612f06565b505050505050565b6001600160401b03831115612f3857612f38612a43565b612f4c83612f468354612e97565b83612ed1565b6000601f841160018114612f805760008515612f685750838201355b600019600387901b1c1916600186901b178355611660565b600083815260209020601f19861690835b82811015612fb15786850135825560209485019460019092019101612f91565b5086821015612fce5760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60408152600061301d604083018688612fe0565b8281036020840152613030818587612fe0565b979650505050505050565b634e487b7160e01b600052603260045260246000fd5b602081526000611a1c602083018486612fe0565b60006001600160401b0380831681810361308157613081612e5e565b6001019392505050565b81516001600160401b038111156130a4576130a4612a43565b6130b8816130b28454612e97565b84612ed1565b602080601f8311600181146130ed57600084156130d55750858301515b600019600386901b1c1916600185901b178555612f19565b600085815260208120601f198616915b8281101561311c578886015182559484019460019091019084016130fd565b508582101561313a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60408152600061315d6040830186612922565b8281036020840152613170818587612fe0565b9695505050505050565b60006020828403121561318c57600080fd5b81516111f281612967565b600061ffff8216806131ab576131ab612e5e565b6000190192915050565b6040815260006131c86040830185612922565b905061ffff831660208301529392505050565b600061ffff80831681810361308157613081612e5e565b6060815260006132056060830186612922565b61ffff8516602084015282810360408401526131708185612922565b8082018082111561090e5761090e612e5e565b6000808335601e1984360301811261324b57600080fd5b8301803591506001600160401b0382111561326557600080fd5b602001915036819003821315610f6957600080fd5b6000808585111561328a57600080fd5b8386111561329757600080fd5b5050820193919092039150565b8035602083101561090e57600019602084900360031b1b1692915050565b634e487b7160e01b600052600160045260246000fdfea26469706673582212208c1875cb11c4334d4d7f887f78c9588d805d170d1be332093828d3e32268139964736f6c63430008170033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000b94704422c2a1e396835a571837aa5ae53285a95000000000000000000000000d3e6775ed9b7dc12b205c8e608dc3767b9e5efda00000000000000000000000079ea96012eea67a83431f1701b3dff7e37f9e282000000000000000000000000f9bba2f07a2c95fc4225f1caec76e6bf04b463e9
-----Decoded View---------------
Arg [0] : ens_ (address): 0xB94704422c2a1E396835A571837Aa5AE53285a95
Arg [1] : registrarController_ (address): 0xd3e6775Ed9B7dC12B205C8E608Dc3767B9e5eFdA
Arg [2] : reverseRegistrar_ (address): 0x79EA96012eEa67A83431F1701B3dFf7e37F9E282
Arg [3] : owner_ (address): 0xf9BbA2F07a2c95fC4225f1CAeC76E6BF04B463e9
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000b94704422c2a1e396835a571837aa5ae53285a95
Arg [1] : 000000000000000000000000d3e6775ed9b7dc12b205c8e608dc3767b9e5efda
Arg [2] : 00000000000000000000000079ea96012eea67a83431f1701b3dff7e37f9e282
Arg [3] : 000000000000000000000000f9bba2f07a2c95fc4225f1caec76e6bf04b463e9
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
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.