Overview
BERA Balance
BERA Value
$22,142.27 (@ $6.05/BERA)More Info
Private Name Tags
ContractCreator
Multichain Info
No addresses found
Latest 25 from a total of 3,861 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Register | 2603134 | 31 mins ago | IN | 4.33863173 BERA | 0 | ||||
Register | 2602679 | 46 mins ago | IN | 4.35336747 BERA | 0 | ||||
Register | 2602369 | 56 mins ago | IN | 4.38604482 BERA | 0 | ||||
Register | 2602369 | 56 mins ago | IN | 4.38548699 BERA | 0 | ||||
Register | 2602050 | 1 hr ago | IN | 4.38850315 BERA | 0 | ||||
Register | 2601421 | 1 hr ago | IN | 4.35792951 BERA | 0 | ||||
Register | 2601187 | 1 hr ago | IN | 4.35045395 BERA | 0.00000002 | ||||
Register | 2600470 | 1 hr ago | IN | 4.30803103 BERA | 0.00000007 | ||||
Register | 2598382 | 3 hrs ago | IN | 4.25094497 BERA | 0.00000003 | ||||
Register | 2586632 | 9 hrs ago | IN | 4.22941367 BERA | 0 | ||||
Register | 2584764 | 10 hrs ago | IN | 4.2548511 BERA | 0 | ||||
Register | 2572063 | 17 hrs ago | IN | 4.22342677 BERA | 0 | ||||
Register | 2560575 | 23 hrs ago | IN | 4.35659416 BERA | 0.00000003 | ||||
Register | 2552417 | 27 hrs ago | IN | 4.31656305 BERA | 0 | ||||
Register | 2520365 | 45 hrs ago | IN | 4.4646427 BERA | 0 | ||||
Register | 2505550 | 2 days ago | IN | 13.08952181 BERA | 0 | ||||
Register | 2496853 | 2 days ago | IN | 12.70263536 BERA | 0 | ||||
Register | 2494191 | 2 days ago | IN | 10.79391037 BERA | 0 | ||||
Register | 2486548 | 2 days ago | IN | 11.31182488 BERA | 0 | ||||
Register | 2475542 | 2 days ago | IN | 3.94443111 BERA | 0 | ||||
Register | 2473284 | 2 days ago | IN | 30.53607267 BERA | 0 | ||||
Register | 2464472 | 3 days ago | IN | 4.01551486 BERA | 0 | ||||
Register | 2464137 | 3 days ago | IN | 4.03488739 BERA | 0.00000012 | ||||
Register | 2463956 | 3 days ago | IN | 4.02081132 BERA | 0 | ||||
Register | 2463856 | 3 days ago | IN | 4.01164583 BERA | 0 |
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
2603134 | 31 mins ago | 0.20075914 BERA | ||||
2602679 | 46 mins ago | 0.20279355 BERA | ||||
2602369 | 56 mins ago | 0.21068671 BERA | ||||
2602369 | 56 mins ago | 0.21012888 BERA | ||||
2602050 | 1 hr ago | 0.2057216 BERA | ||||
2601421 | 1 hr ago | 0.20751509 BERA | ||||
2601187 | 1 hr ago | 0.21000919 BERA | ||||
2600470 | 1 hr ago | 0.20485088 BERA | ||||
2598382 | 3 hrs ago | 0.20263051 BERA | ||||
2586632 | 9 hrs ago | 0.19983901 BERA | ||||
2584764 | 10 hrs ago | 0.20251236 BERA | ||||
2572063 | 17 hrs ago | 0.20256397 BERA | ||||
2560575 | 23 hrs ago | 0.21094095 BERA | ||||
2552417 | 27 hrs ago | 0.20522206 BERA | ||||
2520365 | 45 hrs ago | 0.21261946 BERA | ||||
2505550 | 2 days ago | 0.61737944 BERA | ||||
2496853 | 2 days ago | 0.60974682 BERA | ||||
2494191 | 2 days ago | 0.51249104 BERA | ||||
2486548 | 2 days ago | 0.5359411 BERA | ||||
2475542 | 2 days ago | 0.18792127 BERA | ||||
2473284 | 2 days ago | 1.43944599 BERA | ||||
2464472 | 3 days ago | 0.18903795 BERA | ||||
2464137 | 3 days ago | 0.1940081 BERA | ||||
2463956 | 3 days ago | 0.19719549 BERA | ||||
2463856 | 3 days ago | 0.18839304 BERA |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
RegistrarController
Compiler Version
v0.8.28+commit.7893614a
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.23; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import {BaseRegistrar} from "src/registrar/types/BaseRegistrar.sol"; import {BeraDefaultResolver} from "src/resolver/Resolver.sol"; import {IPriceOracle} from "src/registrar/interfaces/IPriceOracle.sol"; import {IReverseRegistrar} from "src/registrar/interfaces/IReverseRegistrar.sol"; import {IReservedRegistry} from "src/registrar/interfaces/IReservedRegistry.sol"; import {BERA_NODE, GRACE_PERIOD} from "src/utils/Constants.sol"; import {StringUtils} from "src/utils/StringUtils.sol"; /// @title Registrar Controller contract RegistrarController is Ownable, ReentrancyGuard { using StringUtils for string; using SafeERC20 for IERC20; using EnumerableSet for EnumerableSet.Bytes32Set; /// Errors ----------------------------------------------------------- /// @notice Thrown when a name is not available. /// @param name The name that is not available. error NameNotAvailable(string name); /// @notice Thrown when a name's duration is not longer than `MIN_REGISTRATION_DURATION`. /// @param duration The duration that was too short. error DurationTooShort(uint256 duration); /// @notice Thrown when the public sale is not live. error PublicSaleNotLive(); /// @notice Thrown when Multicallable resolver data was specified but not resolver address was provided. error ResolverRequiredWhenDataSupplied(); /// @notice Thrown when the payment received is less than the price. error InsufficientValue(); /// @notice Thrown when the payment receiver is being set to address(0). error InvalidPaymentReceiver(); /// @notice Thrown when a signature has already been used. error SignatureAlreadyUsed(); /// @notice Thrown when a refund transfer is unsuccessful. error TransferFailed(); /// @notice Thrown when a name is reserved. error NameReserved(); /// @notice Thrown when a reverse record is being set for another address. error CantSetReverseRecordForOthers(); /// @notice Thrown when a mint limit for a round is reached. error MintLimitForRoundReached(); /// @notice Thrown when someone tries to mint a reserved name but is not authorised error NotAuthorisedToMintReservedNames(); /// @notice Thrown when the name is not reserved but you try to mint via reserved minting flow error NameNotReserved(); /// @notice Thrown when a free mint signature has already been used. error FreeMintSignatureAlreadyUsed(); /// @notice Thrown when the launch time is in the past. error LaunchTimeInPast(); /// @notice Thrown when a reverse record is not allowed for reserved names. error ReverseRecordNotAllowedForReservedNames(); /// @notice Thrown when the signature is invalid. error InvalidSignature(); /// @notice Thrown when the free mint limit is reached. error FreeMintLimitReached(); /// @notice Thrown when the whitelist signer is invalid. error InvalidWhitelistSigner(); /// @notice Thrown when the free whitelist signer is invalid. error InvalidFreeWhitelistSigner(); /// Events ----------------------------------------------------------- /// @notice Emitted when an ETH payment was processed successfully. /// /// @param payee Address that sent the ETH. /// @param price Value that was paid. event ETHPaymentProcessed(address indexed payee, uint256 price); /// @notice Emitted when a name was registered. /// /// @param name The name that was registered. /// @param label The hashed label of the name. /// @param owner The owner of the name that was registered. /// @param expires The date that the registration expires. event NameRegistered(string name, bytes32 indexed label, address indexed owner, uint256 expires); /// @notice Emitted when a name is registered with a referral. /// /// @dev two different events to keep compatibility with ENS /// @param name The name that was registered /// @param label The hashed label of the name /// @param owner The owner of the name that was registered /// @param referral The address of the referral /// @param expires The date that the registration expires event NameRegisteredWithReferral( string name, bytes32 indexed label, address indexed owner, address indexed referral, uint256 expires ); /// @notice Emitted when a name is renewed. /// /// @param name The name that was renewed. /// @param label The hashed label of the name. /// @param expires The date that the renewed name expires. event NameRenewed(string name, bytes32 indexed label, uint256 expires); /// @notice Emitted when the payment receiver is updated. /// /// @param newPaymentReceiver The address of the new payment receiver. event PaymentReceiverUpdated(address newPaymentReceiver); /// @notice Emitted when the price oracle is updated. /// /// @param newPrices The address of the new price oracle. event PriceOracleUpdated(address newPrices); /// @notice Emitted when the reverse registrar is updated. /// /// @param newReverseRegistrar The address of the new reverse registrar. event ReverseRegistrarUpdated(address newReverseRegistrar); /// @notice Emitted when the launch time is updated. /// /// @param newLaunchTime The new launch time. event LaunchTimeUpdated(uint256 newLaunchTime); /// @notice Emitted when reserved names minter is changed /// /// @param newReservedNameMinterAddress the new address; event ReservedNamesMinterChanged(address newReservedNameMinterAddress); /// @notice Emitted when whitelist authorizer is changed /// /// @param newWhitelistAuthorizerAddress the new address; event WhitelistAuthorizerChanged(address newWhitelistAuthorizerAddress); /// @notice Emitted when free whitelist authorizer is changed /// /// @param newFreeWhitelistAuthorizerAddress the new address; event FreeWhitelistAuthorizerChanged(address newFreeWhitelistAuthorizerAddress); /// Datastructures --------------------------------------------------- /// @notice The details of a registration request. /// @param name The name being registered. /// @param owner The address of the owner for the name. /// @param duration The duration of the registration in seconds. /// @param resolver The address of the resolver to set for this name. /// @param data Multicallable data bytes for setting records in the associated resolver upon reigstration. /// @param reverseRecord Bool to decide whether to set this name as the "primary" name for the `owner`. /// @param referrer The address of the referrer - a zero address indicates no referrer. struct RegisterRequest { string name; address owner; uint256 duration; address resolver; bytes[] data; bool reverseRecord; address referrer; } /// @notice The details of a whitelist registration request. /// @param registerRequest The `RegisterRequest` struct containing the details for the registration. /// @param round_id The ID of the round that the registration is being made in. /// @param round_total_mint The total number of mints allowed in the round. struct WhitelistRegisterRequest { RegisterRequest registerRequest; uint256 round_id; uint256 round_total_mint; } /// Storage ---------------------------------------------------------- /// @notice The implementation of the `BaseRegistrar`. BaseRegistrar immutable base; /// @notice The implementation of the pricing oracle. IPriceOracle public prices; /// @notice The implementation of the Reverse Registrar contract. IReverseRegistrar public reverseRegistrar; /// @notice The implementation of the Reserved Registry contract. IReservedRegistry public reservedRegistry; /// @notice The node for which this name enables registration. It must match the `rootNode` of `base`. bytes32 public immutable rootNode; /// @notice The name for which this registration adds subdomains for, i.e. ".bera". string public rootName; /// @notice The address that will receive ETH funds upon `withdraw()` being called. address public paymentReceiver; /// @notice The mapping of used signatures. mapping(bytes32 => bool) public usedSignatures; /// @notice The mapping of used free mints signatures. mapping(bytes32 => bool) public usedFreeMintsSignatures; /// @notice The mapping of mints count by round by address. /// example: 0x123 => { 1st Round => 3 mints, 2nd Round => 1 mint } mapping(address => mapping(uint256 => uint256)) public mintsCountByRoundByAddress; /// @notice The timestamp of "go-live". Used for setting at-launch pricing premium. uint256 public launchTime; /// Constants -------------------------------------------------------- /// @notice The minimum registration duration, specified in seconds. uint256 public constant MIN_REGISTRATION_DURATION = 365 days; /// @notice The minimum name length. uint256 public constant MIN_NAME_LENGTH = 1; /// @notice The address of the reserved names minter. address private reservedNamesMinter; /// @notice The address of the whitelist authorizer. address private whitelistAuthorizer; /// @notice The address of the free whitelist authorizer. address private freeWhitelistAuthorizer; /// @notice The mapping of free mints count by address. mapping(address => uint8) public freeMintsByAddress; /// Modifiers -------------------------------------------------------- /// @notice Decorator for validating registration requests. /// /// @dev Validates that: /// 1. There is a `resolver` specified` when `data` is set /// 2. That the name is `available()` /// 3. That the registration `duration` is sufficiently long /// /// @param request The RegisterRequest that is being validated. modifier validRegistration(RegisterRequest calldata request) { if (request.data.length > 0 && request.resolver == address(0)) { revert ResolverRequiredWhenDataSupplied(); } if (!available(request.name)) { revert NameNotAvailable(request.name); } if (request.duration < MIN_REGISTRATION_DURATION) { revert DurationTooShort(request.duration); } _; } /// @notice Decorator for validating that the public sale is live. modifier publicSaleLive() { if (block.timestamp < launchTime) revert PublicSaleNotLive(); _; } /// Constructor ------------------------------------------------------ /// @notice Registrar Controller construction sets all of the requisite external contracts. /// /// @dev Assigns ownership of this contract's reverse record to the `owner_`. /// /// @param base_ The base registrar contract. /// @param prices_ The pricing oracle contract. /// @param reverseRegistrar_ The reverse registrar contract. /// @param whitelistSigner_ The whitelist signer contract. /// @param freeWhitelistSigner_ The free whitelist signer contract. /// @param reservedRegistry_ The reserved registry contract. /// @param owner_ The permissioned address initialized as the `owner` in the `Ownable` context. /// @param rootNode_ The node for which this registrar manages registrations. /// @param rootName_ The name of the root node which this registrar manages. /// @param paymentReceiver_ The address that will receive ETH funds upon `withdraw()` being called. constructor( BaseRegistrar base_, IPriceOracle prices_, IReverseRegistrar reverseRegistrar_, address whitelistSigner_, address freeWhitelistSigner_, IReservedRegistry reservedRegistry_, address owner_, bytes32 rootNode_, string memory rootName_, address paymentReceiver_ ) Ownable(owner_) { base = base_; prices = prices_; reverseRegistrar = reverseRegistrar_; if (whitelistSigner_ == address(0)) revert InvalidWhitelistSigner(); whitelistAuthorizer = whitelistSigner_; if (freeWhitelistSigner_ == address(0)) revert InvalidFreeWhitelistSigner(); freeWhitelistAuthorizer = freeWhitelistSigner_; rootNode = rootNode_; rootName = rootName_; paymentReceiver = paymentReceiver_; reservedRegistry = reservedRegistry_; reverseRegistrar.claim(owner_); } /// Admin Functions ------------------------------------------------ /// @notice Allows the `owner` to set the pricing oracle contract. /// /// @dev Emits `PriceOracleUpdated` after setting the `prices` contract. /// /// @param prices_ The new pricing oracle. function setPriceOracle(IPriceOracle prices_) external onlyOwner { prices = prices_; emit PriceOracleUpdated(address(prices_)); } /// @notice Allows the `owner` to set the reverse registrar contract. /// /// @dev Emits `ReverseRegistrarUpdated` after setting the `reverseRegistrar` contract. /// /// @param reverse_ The new reverse registrar contract. function setReverseRegistrar(IReverseRegistrar reverse_) external onlyOwner { reverseRegistrar = reverse_; emit ReverseRegistrarUpdated(address(reverse_)); } /// @notice Allows the `owner` to set the stored `launchTime`. /// /// @param launchTime_ The new launch time timestamp. function setLaunchTime(uint256 launchTime_) external onlyOwner { if (launchTime_ < block.timestamp) { revert LaunchTimeInPast(); } launchTime = launchTime_; emit LaunchTimeUpdated(launchTime_); } /// @notice Allows the `owner` to set the reverse registrar contract. /// /// @dev Emits `PaymentReceiverUpdated` after setting the `paymentReceiver` address. /// /// @param paymentReceiver_ The new payment receiver address. function setPaymentReceiver(address paymentReceiver_) external onlyOwner { if (paymentReceiver_ == address(0)) revert InvalidPaymentReceiver(); paymentReceiver = paymentReceiver_; emit PaymentReceiverUpdated(paymentReceiver_); } /// @notice Checks whether the provided `name` is valid. A name is valid if it's longer than 0 chars and not a single emoji (simple or complex). /// a => valid /// foo => valid /// a💩 => valid /// 💩💩 => valid /// 💩 => invalid /// 👁️ => invalid /// @param name The name to check the length of. /// /// @return `true` if the name is valid, else `false`. function valid(string memory name) public pure returns (bool) { uint256 utfLen = name.utf8Length(); uint256 strlen = name.strlen(); return utfLen > 0 && !(strlen == MIN_NAME_LENGTH && utfLen > MIN_NAME_LENGTH); } /// @notice Checks whether the provided `name` is available. /// /// @param name The name to check the availability of. /// /// @return `true` if the name is `valid` and available on the `base` registrar, else `false`. function available(string memory name) public view returns (bool) { bytes32 label = keccak256(bytes(name)); return valid(name) && base.isAvailable(uint256(label)); } /// @notice Checks the rent price for a provided `name` and `duration`. /// /// @param name The name to check the rent price of. /// @param duration The time that the name would be rented. /// /// @return price The `Price` tuple containing the base and premium prices respectively, denominated in wei. function rentPrice(string memory name, uint256 duration) public view returns (IPriceOracle.Price memory price) { bytes32 label = keccak256(bytes(name)); price = prices.price(name, _getExpiry(uint256(label)), duration); } /// @notice Checks the register price for a provided `name` and `duration`. /// /// @param name The name to check the register price of. /// @param duration The time that the name would be registered. /// /// @return The all-in price for the name registration, denominated in wei. function registerPrice(string memory name, uint256 duration) public view returns (uint256) { IPriceOracle.Price memory price = rentPrice(name, duration); return price.base - price.discount; } /// @notice Enables a caller to register a name. /// /// @dev Validates the registration details via the `validRegistration` modifier. /// This `payable` method must receive appropriate `msg.value` to pass `_validatePayment()`. /// /// @param request The `RegisterRequest` struct containing the details for the registration. function register(RegisterRequest calldata request) public payable publicSaleLive { _validateRegistration(request); _register(request); } /// @notice Allows a whitelisted address to register a name. /// /// @dev Validates the registration details via the `validRegistration` modifier. /// This `payable` method must receive appropriate `msg.value` to pass `_validatePayment()`. /// /// @param request The `RegisterRequest` struct containing the details for the registration. /// @param signature The signature of the whitelisted address. function whitelistRegister(WhitelistRegisterRequest calldata request, bytes calldata signature) public payable { _validateWhitelist(request, signature); _validateRegistration(request.registerRequest); _register(request.registerRequest); } /// @notice Allows a whitelisted address to register a name for free /// /// @param request The `RegisterRequest` struct containing the details for the registration. /// @param signature The signature of the whitelisted address. function whitelistFreeRegister(RegisterRequest calldata request, bytes calldata signature) public validRegistration(request) { _validateFreeWhitelist(request, signature); uint256 strlen = request.name.strlen(); if (strlen < 3) revert NameNotAvailable(request.name); _validateRegistration(request); _registerRequest(request); } /// @notice Allows the reserved names minter to register a reserved name. /// /// @dev Skips the _validateRegistration because it's callable only by reservedNamesMinter /// @dev Calls the _registerRequest directly because it's not payable, so we don't need to validate payment /// /// @param request The `RegisterRequest` struct containing the details for the registration. function reservedRegister(RegisterRequest calldata request) public validRegistration(request) { if (msg.sender != reservedNamesMinter) { revert NotAuthorisedToMintReservedNames(); } if (!reservedRegistry.isReservedName(request.name)) revert NameNotReserved(); if (request.reverseRecord) revert ReverseRecordNotAllowedForReservedNames(); _registerRequest(request); } /// @notice Internal helper for registering a name. /// /// @dev Validates the registration details via the `validRegistration` modifier. /// This `payable` method must receive appropriate `msg.value` to pass `_validatePayment()`. /// /// @param request The `RegisterRequest` struct containing the details for the registration. function _register(RegisterRequest calldata request) internal validRegistration(request) { uint256 price = registerPrice(request.name, request.duration); _validatePayment(price); _registerRequest(request); _refundExcessEth(price); } /// @notice Allows a caller to renew a name for a specified duration. /// /// @dev This `payable` method must receive appropriate `msg.value` to pass `_validatePayment()`. /// The price for renewal never incorporates pricing `premium`. This is because we only expect /// renewal on names that are not expired or are in the grace period. Use the `base` price returned /// by the `rentPrice` tuple to determine the price for calling this method. /// /// @param name The name that is being renewed. /// @param duration The duration to extend the expiry, in seconds. function renew(string calldata name, uint256 duration) external payable { bytes32 labelhash = keccak256(bytes(name)); uint256 tokenId = uint256(labelhash); uint256 price = registerPrice(name, duration); _validatePayment(price); uint256 expires = base.renew(tokenId, duration); _refundExcessEth(price); emit NameRenewed(name, labelhash, expires); } /// @notice Internal helper for validating ETH payments /// /// @dev Emits `ETHPaymentProcessed` after validating the payment. /// /// @param price The expected value. function _validatePayment(uint256 price) internal { if (msg.value < price) { revert InsufficientValue(); } emit ETHPaymentProcessed(msg.sender, price); } function _validateRegistration(RegisterRequest calldata request) internal view { if (reservedRegistry.isReservedName(request.name)) revert NameReserved(); if (request.owner != msg.sender && request.reverseRecord) revert CantSetReverseRecordForOthers(); } /// @notice Validates the whitelist registration request and signature. /// @param request The `WhitelistRegisterRequest` struct containing the details for the registration. /// @param signature The signature of the whitelisted address. /// @dev Encodes the payload following the WhitelistRegisterRequest struct order. Writes the payload hash to the `usedSignatures` mapping. /// @dev Checks if the payload hash has already been used. /// @dev Checks if the mint count for the round has not exceeded the total mint limit. /// @dev Checks if the signer is the whitelist authorizer. function _validateWhitelist(WhitelistRegisterRequest calldata request, bytes calldata signature) internal { bytes memory payload = abi.encode( request.registerRequest.name, request.registerRequest.owner, request.registerRequest.duration, request.registerRequest.resolver, request.registerRequest.data, request.registerRequest.reverseRecord, request.registerRequest.referrer, request.round_id, request.round_total_mint ); bytes32 payloadHash = generatePersonalPayloadHash(payload); if (usedSignatures[payloadHash]) revert SignatureAlreadyUsed(); if (mintsCountByRoundByAddress[msg.sender][request.round_id] >= request.round_total_mint) { revert MintLimitForRoundReached(); } address signer = getSignerFromSignature(payloadHash, signature); if (signer == address(0) || signer != whitelistAuthorizer) revert InvalidSignature(); usedSignatures[payloadHash] = true; mintsCountByRoundByAddress[msg.sender][request.round_id]++; } /// @notice Validates the free whitelist registration request and signature. /// @param request The `RegisterRequest` struct containing the details for the registration. /// @param signature The signature of the whitelisted address. /// @dev Encodes the payload following the RegisterRequest struct order. Writes the payload hash to the `usedFreeMintsSignatures` mapping. /// @dev Checks if the payload hash has already been used. /// @dev Checks if the owner has just one free mint. function _validateFreeWhitelist(RegisterRequest calldata request, bytes calldata signature) internal { bytes memory payload = abi.encode( request.name, request.owner, request.duration, request.resolver, request.data, request.reverseRecord, request.referrer ); bytes32 payloadHash = generatePersonalPayloadHash(payload); if (usedFreeMintsSignatures[payloadHash]) revert FreeMintSignatureAlreadyUsed(); if (freeMintsByAddress[msg.sender] != 0) revert FreeMintLimitReached(); address signer = getSignerFromSignature(payloadHash, signature); if (signer == address(0) || signer != freeWhitelistAuthorizer) revert InvalidSignature(); usedFreeMintsSignatures[payloadHash] = true; freeMintsByAddress[msg.sender]++; } function generatePersonalPayloadHash(bytes memory payload) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", keccak256(payload))); } function getSignerFromSignature(bytes32 payloadHash, bytes calldata signature) internal pure returns (address) { return ECDSA.recover(payloadHash, signature); } /// @notice Get the whitelist authorizer. /// @return The address of the whitelist authorizer. function getWhitelistAuthorizer() public view returns (address) { return whitelistAuthorizer; } /// @notice Get the free whitelist authorizer. /// @return The address of the free whitelist authorizer. function getFreeWhitelistAuthorizer() public view returns (address) { return freeWhitelistAuthorizer; } /// @notice Get the reserved names minter. /// @return The address of the reserved names minter. function getReservedNamesMinter() public view returns (address) { return reservedNamesMinter; } /// @notice Helper for deciding whether to include a launch-premium. /// /// @dev If the token returns a `0` expiry time, it hasn't been registered before. On launch, this will be true for all /// names. Use the `launchTime` to establish a premium price around the actual launch time. /// /// @param tokenId The ID of the token to check for expiry. /// /// @return expires Returns the expiry + GRACE_PERIOD for previously registered names, else `launchTime`. function _getExpiry(uint256 tokenId) internal view returns (uint256 expires) { expires = base.nameExpires(bytes32(tokenId)); if (expires == 0) { return launchTime; } return expires + GRACE_PERIOD; } /// @notice Shared registration logic for both `register()` and `whitelistRegister()`. /// /// @dev Will set records in the specified resolver if the resolver address is non zero and there is `data` in the `request`. /// Will set the reverse record's owner as msg.sender if `reverseRecord` is `true`. /// Emits `NameRegistered` upon successful registration. /// /// @param request The `RegisterRequest` struct containing the details for the registration. function _registerRequest(RegisterRequest calldata request) internal { uint256 expires = base.registerWithRecord( uint256(keccak256(bytes(request.name))), request.owner, request.duration, request.resolver, 0 ); if (request.data.length > 0) { _setRecords(request.resolver, keccak256(bytes(request.name)), request.data); } if (request.reverseRecord) { _setReverseRecord(request.name, request.resolver, msg.sender); } // two different events for ENS compatibility emit NameRegistered(request.name, keccak256(bytes(request.name)), request.owner, expires); if (request.referrer != address(0)) { emit NameRegisteredWithReferral( request.name, keccak256(bytes(request.name)), request.owner, request.referrer, expires ); } } /// @notice Refunds any remaining `msg.value` after processing a registration or renewal given`price`. /// @param price The total value to be retained, denominated in wei. function _refundExcessEth(uint256 price) internal nonReentrant { if (msg.value > price) { (bool sent,) = payable(msg.sender).call{value: (msg.value - price)}(""); if (!sent) revert TransferFailed(); } } /// @notice Uses Multicallable to iteratively set records on a specified resolver. /// @dev `multicallWithNodeCheck` ensures that each record being set is for the specified `label`. /// @param resolverAddress The address of the resolver to set records on. /// @param label The keccak256 namehash for the specified name. /// @param data The abi encoded calldata records that will be used in the multicallable resolver. function _setRecords(address resolverAddress, bytes32 label, bytes[] calldata data) internal { bytes32 nodehash = keccak256(abi.encodePacked(rootNode, label)); BeraDefaultResolver resolver = BeraDefaultResolver(resolverAddress); resolver.multicallWithNodeCheck(nodehash, data); } /// @notice Sets the reverse record to `owner` for a specified `name` on the specified `resolver. /// @param name The specified name. /// @param resolver The resolver to set the reverse record on. /// @param owner The owner of the reverse record. function _setReverseRecord(string memory name, address resolver, address owner) internal { reverseRegistrar.setNameForAddr(msg.sender, owner, resolver, string.concat(name, rootName)); } /// @notice Allows anyone to withdraw the eth accumulated on this contract back to the `paymentReceiver`. function withdrawETH() public { (bool sent,) = payable(paymentReceiver).call{value: (address(this).balance)}(""); if (!sent) revert TransferFailed(); } /// @notice Allows the owner to recover ERC20 tokens sent to the contract by mistake. function recoverFunds(address _token, address _to, uint256 _amount) external onlyOwner { IERC20(_token).safeTransfer(_to, _amount); } /// @notice Allows the owner to set the reserved names minter. /// @param reservedNamesMinter_ The address of the reserved names minter. function setReservedNamesMinter(address reservedNamesMinter_) external onlyOwner { reservedNamesMinter = reservedNamesMinter_; emit ReservedNamesMinterChanged(reservedNamesMinter); } function setWhitelistAuthorizer(address _whitelistAuthorizer) external onlyOwner { whitelistAuthorizer = _whitelistAuthorizer; emit WhitelistAuthorizerChanged(_whitelistAuthorizer); } function setFreeWhitelistAuthorizer(address _freeWhitelistAuthorizer) external onlyOwner { freeWhitelistAuthorizer = _freeWhitelistAuthorizer; emit FreeWhitelistAuthorizerChanged(_freeWhitelistAuthorizer); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; import {IERC20Permit} from "../extensions/IERC20Permit.sol"; import {Address} from "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev An operation with an ERC20 token failed. */ error SafeERC20FailedOperation(address token); /** * @dev Indicates a failed `decreaseAllowance` request. */ error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value))); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value))); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); forceApprove(token, spender, oldAllowance + value); } /** * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no * value, non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { unchecked { uint256 currentAllowance = token.allowance(address(this), spender); if (currentAllowance < requestedDecrease) { revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); } forceApprove(token, spender, currentAllowance - requestedDecrease); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value)); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); _callOptionalReturn(token, approvalCall); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data); if (returndata.length != 0 && !abi.decode(returndata, (bool))) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. pragma solidity ^0.8.20; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ```solidity * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure * unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an * array of EnumerableSet. * ==== */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position is the index of the value in the `values` array plus 1. // Position 0 is used to mean a value is not in the set. mapping(bytes32 value => uint256) _positions; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._positions[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We cache the value's position to prevent multiple reads from the same storage slot uint256 position = set._positions[value]; if (position != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 valueIndex = position - 1; uint256 lastIndex = set._values.length - 1; if (valueIndex != lastIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the lastValue to the index where the value to delete is set._values[valueIndex] = lastValue; // Update the tracked position of the lastValue (that was just moved) set._positions[lastValue] = position; } // Delete the slot where the moved value was stored set._values.pop(); // Delete the tracked position for the deleted slot delete set._positions[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._positions[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { bytes32[] memory store = _values(set._inner); bytes32[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values in the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {Context} from "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol) pragma solidity ^0.8.20; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant NOT_ENTERED = 1; uint256 private constant ENTERED = 2; uint256 private _status; /** * @dev Unauthorized reentrant call. */ error ReentrancyGuardReentrantCall(); constructor() { _status = NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be NOT_ENTERED if (_status == ENTERED) { revert ReentrancyGuardReentrantCall(); } // Any calls to nonReentrant after this point will fail _status = ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.20; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS } /** * @dev The signature derives the `address(0)`. */ error ECDSAInvalidSignature(); /** * @dev The signature has an invalid length. */ error ECDSAInvalidSignatureLength(uint256 length); /** * @dev The signature has an S value that is in the upper half order. */ error ECDSAInvalidSignatureS(bytes32 s); /** * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not * return address(0) without also returning an error description. Errors are documented using an enum (error type) * and a bytes32 providing additional information about the error. * * If no error is returned, then the address can be used for verification purposes. * * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError, bytes32) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length)); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature); _throwError(error, errorArg); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] */ function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError, bytes32) { unchecked { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); // We do not check for an overflow here since the shift operation results in 0 or 1. uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. */ function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs); _throwError(error, errorArg); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError, bytes32) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS, s); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature, bytes32(0)); } return (signer, RecoverError.NoError, bytes32(0)); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s); _throwError(error, errorArg); return recovered; } /** * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided. */ function _throwError(RecoverError error, bytes32 errorArg) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert ECDSAInvalidSignature(); } else if (error == RecoverError.InvalidSignatureLength) { revert ECDSAInvalidSignatureLength(uint256(errorArg)); } else if (error == RecoverError.InvalidSignatureS) { revert ECDSAInvalidSignatureS(errorArg); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.23; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; import {IERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; import {BNS} from "src/registry/interfaces/BNS.sol"; import {GRACE_PERIOD, RECLAIM_ID} from "src/utils/Constants.sol"; /// @title Base Registrar contract BaseRegistrar is ERC721, Ownable { using Strings for uint256; /// Errors ----------------------------------------------------------- /// @notice Thrown when the name has expired. /// /// @param tokenId The id of the token that expired. error Expired(uint256 tokenId); /// @notice Thrown when called by an unauthorized owner. /// /// @param tokenId The id that was being called against. /// @param sender The unauthorized sender. error NotApprovedOwner(uint256 tokenId, address sender); /// @notice Thrown when the name is not available for registration. /// /// @param tokenId The id of the name that is not available. error NotAvailable(uint256 tokenId); /// @notice Thrown when the queried tokenId does not exist. /// /// @param tokenId The id of the name that does not exist. error NonexistentToken(uint256 tokenId); /// @notice Thrown when the name is not registered or in its Grace Period. /// /// @param tokenId The id of the token that is not registered or in Grace Period. error NotRegisteredOrInGrace(uint256 tokenId); /// @notice Thrown when msg.sender is not an approved Controller. error OnlyController(); /// @notice Thrown when this contract does not own the `baseNode`. error RegistrarNotLive(); /// Events ----------------------------------------------------------- /// @notice Emitted when a Controller is added to the approved `controllers` mapping. /// /// @param controller The address of the approved controller. event ControllerAdded(address indexed controller); /// @notice Emitted when a Controller is removed from the approved `controllers` mapping. /// /// @param controller The address of the removed controller. event ControllerRemoved(address indexed controller); /// @notice Emitted when a name is registered. /// /// @param id The id of the registered name. /// @param owner The owner of the registered name. /// @param expires The expiry of the new ownership record. event NameRegistered(uint256 indexed id, address indexed owner, uint256 expires); /// @notice Emitted when a name is renewed. /// /// @param id The id of the renewed name. /// @param expires The new expiry for the name. event NameRenewed(uint256 indexed id, uint256 expires); /// @notice Emitted when a name is registered with BNS Records. /// /// @param id The id of the newly registered name. /// @param owner The owner of the registered name. /// @param expires The expiry of the new ownership record. /// @param resolver The address of the resolver for the name. /// @param ttl The time-to-live for the name. event NameRegisteredWithRecord( uint256 indexed id, address indexed owner, uint256 expires, address resolver, uint64 ttl ); /// @notice Emitted when metadata for a token range is updated. /// /// @dev Useful for third-party platforms such as NFT marketplaces who can update /// the images and related attributes of the NFTs in a timely fashion. /// To refresh a whole collection, emit `_toTokenId` with `type(uint256).max` /// ERC-4906: https://eip.tools/eip/4906 /// /// @param _fromTokenId The starting range of `tokenId` for which metadata has been updated. /// @param _toTokenId The ending range of `tokenId` for which metadata has been updated. event BatchMetadataUpdate(uint256 _fromTokenId, uint256 _toTokenId); /// @notice Emitted when the metadata for the contract collection is updated. /// /// @dev ERC-7572: https://eips.ethereum.org/EIPS/eip-7572 event ContractURIUpdated(); /// Storage ---------------------------------------------------------- /// @notice The Registry contract. BNS public immutable registry; /// @notice A map of expiry times to node. mapping(bytes32 node => uint256 expiry) public nameExpires; /// @notice The namehash of the TLD this registrar owns (eg, .bera). bytes32 public immutable baseNode; /// @notice The base URI for token metadata. string private _tokenURI; /// @notice The URI for collection metadata. string private _collectionURI; /// @notice A map of addresses that are authorised to register and renew names. mapping(address controller => bool isApproved) public controllers; /// Modifiers -------------------------------------------------------- /// @notice Decorator for determining if the contract is actively managing registrations for its `baseNode`. modifier live() { if (registry.owner(baseNode) != address(this)) { revert RegistrarNotLive(); } _; } /// @notice Decorator for restricting methods to only approved Controller callers. modifier onlyController() { if (!controllers[msg.sender]) revert OnlyController(); _; } /// @notice Decorator for determining if a name is available. /// /// @param id The id being checked for availability. modifier onlyAvailable(uint256 id) { if (!isAvailable(id)) revert NotAvailable(id); _; } /// @notice Decorator for determining if a name has expired. /// /// @param id The id being checked for expiry. modifier onlyNonExpired(uint256 id) { if (nameExpires[bytes32(id)] <= block.timestamp) revert Expired(id); _; } /// Constructor ------------------------------------------------------ /// @notice BaseRegistrar constructor used to initialize the configuration of the implementation. /// /// @param registry_ The Registry contract. /// @param owner_ The permissioned address initialized as the `owner` in the `Ownable` context. /// @param baseNode_ The node that this contract manages registrations for. /// @param tokenURI_ The base token URI for NFT metadata. /// @param collectionURI_ The URI for the collection's metadata. constructor(BNS registry_, address owner_, bytes32 baseNode_, string memory tokenURI_, string memory collectionURI_) ERC721("Beranames", unicode"🐻🪪") Ownable(owner_) { _transferOwnership(owner_); registry = registry_; baseNode = baseNode_; _tokenURI = tokenURI_; _collectionURI = collectionURI_; } /// Admin Functions -------------------------------------------------- /// @notice Authorises a controller, who can register and renew domains. /// @dev Emits `ControllerAdded(controller)` after adding the `controller` to the `controllers` mapping. /// @param controller The address of the new controller. function addController(address controller) external onlyOwner { controllers[controller] = true; emit ControllerAdded(controller); } /// @notice Revoke controller permission for an address. /// @dev Emits `ControllerRemoved(controller)` after removing the `controller` from the `controllers` mapping. /// @param controller The address of the controller to remove. function removeController(address controller) external onlyOwner { controllers[controller] = false; emit ControllerRemoved(controller); } /// @notice Set the resolver for the node this registrar manages. /// @param resolver The address of the new resolver contract. function setResolver(address resolver) external onlyOwner { registry.setResolver(baseNode, resolver); } /// @notice Register a name and add details to the record in the Registry. /// @param id The token id determined by keccak256(label). /// @param owner The address that should own the registration. /// @param duration Duration in seconds for the registration. /// @param resolver Address of the resolver for the name. /// @param ttl Time-to-live for the name. function registerWithRecord(uint256 id, address owner, uint256 duration, address resolver, uint64 ttl) external live onlyController onlyAvailable(id) returns (uint256) { uint256 expiry = _localRegister(id, owner, duration); registry.setSubnodeRecord(baseNode, bytes32(id), owner, resolver, ttl); emit NameRegisteredWithRecord(id, owner, expiry, resolver, ttl); return expiry; } /// @notice Gets the owner of the specified token ID. /// @dev Names become unowned when their registration expires. /// @param tokenId The id of the name to query the owner of. /// @return address The address currently marked as the owner of the given token ID. function ownerOf(uint256 tokenId) public view override onlyNonExpired(tokenId) returns (address) { return super.ownerOf(tokenId); } /// @notice Returns true if the specified name is available for registration. /// @param id The id of the name to check availability of. /// @return `true` if the name is available, else `false`. function isAvailable(uint256 id) public view returns (bool) { // Not available if it's registered here or in its grace period. return nameExpires[bytes32(id)] + GRACE_PERIOD < block.timestamp; } /// @notice Allows holders of names to renew their ownerhsip and extend their expiry. /// @param id The id of the name to renew. /// @param duration The time that will be added to this name's expiry. /// @return The new expiry date. function renew(uint256 id, uint256 duration) external live onlyController returns (uint256) { uint256 expires = nameExpires[bytes32(id)]; if (expires + GRACE_PERIOD < block.timestamp) { revert NotRegisteredOrInGrace(id); } expires += duration; nameExpires[bytes32(id)] = expires; emit NameRenewed(id, expires); return expires; } /// @notice ERC165 compliant signal for interface support. /// @param interfaceID the ERC165 iface id being checked for compliance /// @return bool Whether this contract supports the provided interfaceID function supportsInterface(bytes4 interfaceID) public pure override(ERC721) returns (bool) { return interfaceID == type(IERC165).interfaceId || interfaceID == type(IERC721).interfaceId || interfaceID == RECLAIM_ID; } /// ERC721 Implementation -------------------------------------------- /// @notice Returns the Uniform Resource Identifier (URI) for token `id`. /// @dev Reverts if the `tokenId` has not be registered. /// @param tokenId The token for which to return the metadata uri. /// @return The URI for the specified `tokenId`. function tokenURI(uint256 tokenId) public view override returns (string memory) { if (_ownerOf(tokenId) == address(0)) revert NonexistentToken(tokenId); return bytes(_tokenURI).length > 0 ? string.concat(_tokenURI, tokenId.toString()) : ""; } /// @notice Returns the Uniform Resource Identifier (URI) for the contract. /// @dev ERC-7572: https://eips.ethereum.org/EIPS/eip-7572 function contractURI() public view returns (string memory) { return _collectionURI; } /// @dev Allows the owner to set the the base Uniform Resource Identifier (URI)`. /// Emits the `BatchMetadataUpdate` event for the full range of valid `tokenIds`. function setTokenURI(string memory baseURI_) public onlyOwner { _tokenURI = baseURI_; /// @dev minimum valid tokenId is `1` because uint256(nodehash) will never be called against `nodehash == 0x0`. emit BatchMetadataUpdate(1, type(uint256).max); } /// @dev Allows the owner to set the the contract Uniform Resource Identifier (URI)`. /// Emits the `ContractURIUpdated` event. function setContractURI(string memory collectionURI_) public onlyOwner { _collectionURI = collectionURI_; emit ContractURIUpdated(); } /// @notice transferFrom is overridden to handle the registry update. function transferFrom(address from, address to, uint256 tokenId) public override { super.transferFrom(from, to, tokenId); registry.setSubnodeOwner(baseNode, bytes32(tokenId), to); } /// Internal Methods ------------------------------------------------- /// @notice Register a name and possibly update the Registry. /// @param id The token id determined by keccak256(label). /// @param owner The address that should own the registration. /// @param duration Duration in seconds for the registration. /// @param updateRegistry Whether to update the Regstiry with the ownership change /// /// @return The expiry date of the registered name. function _register(uint256 id, address owner, uint256 duration, bool updateRegistry) internal live onlyController onlyAvailable(id) returns (uint256) { uint256 expiry = _localRegister(id, owner, duration); if (updateRegistry) { registry.setSubnodeOwner(baseNode, bytes32(id), owner); } emit NameRegistered(id, owner, expiry); return expiry; } /// @notice Internal handler for local state changes during registrations. /// @dev Sets the token's expiry time and then `burn`s and `mint`s a new token. /// @param id The token id determined by keccak256(label). /// @param owner The address that should own the registration. /// @param duration Duration in seconds for the registration. /// /// @return expiry The expiry date of the registered name. function _localRegister(uint256 id, address owner, uint256 duration) internal returns (uint256 expiry) { expiry = block.timestamp + duration; nameExpires[bytes32(id)] = expiry; if (_ownerOf(id) != address(0)) { // Name was previously owned, and expired _burn(id); } _mint(owner, id); } /// @notice Returns whether the given spender can transfer a given token ID. /// @param spender address of the spender to query /// @param tokenId uint256 ID of the token to be transferred /// @return `true` if msg.sender is approved for the given token ID, is an operator of the owner, /// or is the owner of the token, else `false`. function _isApprovedOrOwner(address spender, uint256 tokenId) internal view onlyNonExpired(tokenId) returns (bool) { address owner_ = _ownerOf(tokenId); return owner_ == spender || _isAuthorized(owner_, spender, tokenId); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.23; // Admin Controller import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; // Bera Name Service import {BNS} from "src/registry/interfaces/BNS.sol"; // Interfaces import {IExtendedResolver} from "src/resolver/interfaces/IExtendedResolver.sol"; import {IReverseRegistrar} from "src/registrar/interfaces/IReverseRegistrar.sol"; // Resolver Profiles import {ABIResolver} from "src/resolver/profiles/ABIResolver.sol"; import {AddrResolver} from "src/resolver/profiles/AddrResolver.sol"; import {ContentHashResolver} from "src/resolver/profiles/ContentHashResolver.sol"; // import {DNSResolver} from "src/resolver/profiles/DNSResolver.sol"; import {ExtendedResolver} from "src/resolver/profiles/ExtendedResolver.sol"; import {InterfaceResolver} from "src/resolver/profiles/InterfaceResolver.sol"; import {Multicallable} from "src/resolver/types/Multicallable.sol"; import {NameResolver} from "src/resolver/profiles/NameResolver.sol"; import {PubkeyResolver} from "src/resolver/profiles/PubkeyResolver.sol"; import {TextResolver} from "src/resolver/profiles/TextResolver.sol"; /// @title BeraResolver contract BeraDefaultResolver is // Accessability Controller Multicallable, // Resolvers ABIResolver, AddrResolver, ContentHashResolver, // DNSResolver, InterfaceResolver, NameResolver, PubkeyResolver, TextResolver, ExtendedResolver, // Admin Controller Ownable { /// Errors ----------------------------------------------------------- /// @notice Thown when msg.sender tries to set itself as an operator/delegate. error CantSetSelf(); /// @notice Thown when the registrar controller is not set. error InvalidRegistrarController(); /// @notice Thown when the reverse registrar is not set. error InvalidReverseRegistrar(); /// @notice Thown when the caller is not the owner of the node. error NotOwner(); /// Storage ---------------------------------------------------------- /// @notice The BNS registry. BNS public immutable bns; /// @notice The trusted registrar controller contract. address public registrarController; /// @notice The reverse registrar contract. address public reverseRegistrar; /// @notice A mapping of account operators: can control owner's nodes. mapping(address owner => mapping(address operator => bool isApproved)) private _operatorApprovals; /// @notice A mapping node operators: can control a specific node. mapping(address owner => mapping(bytes32 node => mapping(address delegate => bool isApproved))) private _tokenApprovals; /// 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); /// Constructor ------------------------------------------------------ /// @notice L2 Resolver constructor used to establish the necessary contract configuration. /// /// @param bns_ 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(BNS bns_, address registrarController_, address reverseRegistrar_, address owner_) Ownable(owner_) { // Set state bns = bns_; if (registrarController_ == address(0)) revert InvalidRegistrarController(); if (reverseRegistrar_ == address(0)) revert InvalidReverseRegistrar(); registrarController = registrarController_; reverseRegistrar = reverseRegistrar_; // Initialize reverse registrar IReverseRegistrar(reverseRegistrar_).claim(owner_); } /// Authorisation Functions ----------------------------------------- /// @dev See {IERC1155-setApprovalForAll}. function setApprovalForAll(address operator, bool approved) external { if (msg.sender == operator) revert CantSetSelf(); _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. /// /// @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 CantSetSelf(); if (msg.sender != bns.owner(node)) revert NotOwner(); _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 = bns.owner(node); return owner == msg.sender || isApprovedForAll(owner, msg.sender) || isApprovedFor(owner, node, msg.sender); } /// ERC165 Interface Support ----------------------------------------- /// @notice ERC165 compliant signal for interface support. /// @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)); } /// Admin Functions -------------------------------------------------- /// @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 { if (registrarController_ == address(0)) revert InvalidRegistrarController(); 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 { if (reverseRegistrar_ == address(0)) revert InvalidReverseRegistrar(); reverseRegistrar = reverseRegistrar_; emit ReverseRegistrarUpdated(reverseRegistrar_); } }
//SPDX-License-Identifier: MIT pragma solidity >=0.8.17 <0.9.0; interface IPriceOracle { /// @notice The payment method for registration. enum Payment { BERA, STABLE } /// @notice The price for a given label. struct Price { uint256 base; uint256 discount; } /// @notice The price for a given label. /// This assumes a default payment method of BERA. /// @param label The label to query. /// @param expires The expiry of the label. /// @param duration The duration of the registration. /// @return The price of the label. function price(string calldata label, uint256 expires, uint256 duration) external view returns (Price memory); /// @notice The price for a given label. /// @param label The label to query. /// @param expires The expiry of the label. /// @param duration The duration of the registration. /// @param payment The payment method. /// @return The price of the label. function price(string calldata label, uint256 expires, uint256 duration, Payment payment) external view returns (Price memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.23; interface IReverseRegistrar { /// @notice Thrown when the registry is invalid. error InvalidRegistry(); function claim(address claimant) external returns (bytes32); function setNameForAddr(address addr, address owner, address resolver, string memory name) external returns (bytes32); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.23; interface IReservedRegistry { function isReservedName(string memory name) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.23; // @param BERA_NODE The node hash of "bera" bytes32 constant BERA_NODE = 0xcac7291742cc038df280cfdc67517aa5d83fe6f4716c336481273a83a877997b; // @param REVERSE_NODE The node hash of "reverse" bytes32 constant REVERSE_NODE = 0xa097f6721ce401e757d1223a763fef49b8b5f90bb18567ddb86fd205dff71d34; // @param ADDR_REVERSE_NODE The node hash of "addr.reverse" bytes32 constant ADDR_REVERSE_NODE = 0x91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e2; // @param GRACE_PERIOD the grace period for expired names uint256 constant GRACE_PERIOD = 30 days; // @param RECLAIM_ID InterfaceId for the Reclaim interface bytes4 constant RECLAIM_ID = bytes4(keccak256("reclaim(uint256,address)")); uint64 constant DEFAULT_TTL = 3600;
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; library StringUtils { error InvalidUTF8Byte(); function utf8Length(string memory s) internal pure returns (uint256) { return bytes(s).length; } /** * @dev Returns the length of a given string, accurately counting characters including complex emojis. * @param s The string to measure the length of. * @return The length of the input string. */ function strlen(string memory s) internal pure returns (uint256) { bytes memory strBytes = bytes(s); uint256 len = 0; uint256 i = 0; uint256 strLen = strBytes.length; while (i < strLen) { uint256 charLen = _charLength(strBytes, i); uint256 nextI = i + charLen; // Include any combining marks or modifiers immediately following the base character while (nextI < strLen && _isCombiningMarkOrModifier(strBytes, nextI)) { nextI += _charLength(strBytes, nextI); } // Handle sequences involving ZWJs by looping until no more ZWJs are found while (nextI < strLen && _isZeroWidthJoiner(strBytes, nextI)) { // Move past the ZWJ nextI += _charLength(strBytes, nextI); // Include the next character after ZWJ if (nextI < strLen) { uint256 nextCharLen = _charLength(strBytes, nextI); nextI += nextCharLen; // Include any combining marks or modifiers following the character while (nextI < strLen && _isCombiningMarkOrModifier(strBytes, nextI)) { nextI += _charLength(strBytes, nextI); } } else { break; // No character after ZWJ } } // Handle regional indicators (used in flags) - always count as pairs if (_isRegionalIndicator(strBytes, i) && nextI < strLen && _isRegionalIndicator(strBytes, nextI)) { nextI += _charLength(strBytes, nextI); } // Increment length for each complete character sequence len++; i = nextI; } return len; } // Determines the length of a UTF-8 encoded character in bytes with validation function _charLength(bytes memory strBytes, uint256 index) private pure returns (uint256) { uint8 b = uint8(strBytes[index]); if (b < 0x80) { return 1; // 1-byte character (ASCII) } else if (b < 0xE0 && index + 1 < strBytes.length && uint8(strBytes[index + 1]) & 0xC0 == 0x80) { return 2; // 2-byte character } else if ( b < 0xF0 && index + 2 < strBytes.length && uint8(strBytes[index + 1]) & 0xC0 == 0x80 && uint8(strBytes[index + 2]) & 0xC0 == 0x80 ) { return 3; // 3-byte character } else if ( b < 0xF8 && index + 3 < strBytes.length && uint8(strBytes[index + 1]) & 0xC0 == 0x80 && uint8(strBytes[index + 2]) & 0xC0 == 0x80 && uint8(strBytes[index + 3]) & 0xC0 == 0x80 ) { return 4; // 4-byte character (including emojis) } else { revert InvalidUTF8Byte(); } } // Checks if the sequence starting at index is a Zero-Width Joiner (ZWJ) function _isZeroWidthJoiner(bytes memory strBytes, uint256 index) private pure returns (bool) { return ( strBytes[index] == 0xE2 && index + 2 < strBytes.length && strBytes[index + 1] == 0x80 && strBytes[index + 2] == 0x8D ); } // Checks if the character at index is a combining mark or modifier function _isCombiningMarkOrModifier(bytes memory strBytes, uint256 index) private pure returns (bool) { uint8 b = uint8(strBytes[index]); // Combining marks are in the range starting with 0xCC or 0xCD if (b == 0xCC || b == 0xCD) { return true; } // Emoji modifiers and variation selectors if (b == 0xE2 && index + 2 < strBytes.length) { uint8 b1 = uint8(strBytes[index + 1]); uint8 b2 = uint8(strBytes[index + 2]); // Check for variation selectors (e.g., U+FE0F) if (b1 == 0x80 && (b2 == 0x8F || b2 == 0x8E)) { return true; } } // Handle emojis with skin tone, gender modifiers, etc. if (b == 0xF0 && index + 3 < strBytes.length) { uint8 b1 = uint8(strBytes[index + 1]); uint8 b2 = uint8(strBytes[index + 2]); uint8 b3 = uint8(strBytes[index + 3]); // Check for specific sequences that are known modifiers if ( (b1 == 0x9F && b2 == 0x8F && (b3 >= 0xBB && b3 <= 0xBF)) // Skin tone modifiers || (b1 == 0x9F && b2 == 0xA4 && b3 == 0xB0) ) { // Gender modifiers return true; } } // Check for Variation Selector-16 (U+FE0F) if (b == 0xEF && index + 2 < strBytes.length) { uint8 b1 = uint8(strBytes[index + 1]); uint8 b2 = uint8(strBytes[index + 2]); if (b1 == 0xB8 && b2 == 0x8F) { return true; } } // Check for Combining Enclosing Keycap (U+20E3) if (b == 0xE2 && index + 2 < strBytes.length) { uint8 b1 = uint8(strBytes[index + 1]); uint8 b2 = uint8(strBytes[index + 2]); if (b1 == 0x83 && b2 == 0xA3) { return true; } } // Checks if the character at index is a Tag Indicator (used in special flag sequences) if ( b == 0xF3 && index + 2 < strBytes.length && strBytes[index + 1] == 0xA0 && strBytes[index + 2] >= 0x80 && strBytes[index + 2] <= 0x9F ) { return true; } return false; } // Checks if the character at index is a Regional Indicator Symbol (used for flag emojis) function _isRegionalIndicator(bytes memory strBytes, uint256 index) private pure returns (bool) { return ( strBytes[index] == 0xF0 && index + 3 < strBytes.length && strBytes[index + 1] == 0x9F && strBytes[index + 2] == 0x87 ); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {FailedInnerCall} error. * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert AddressInsufficientBalance(address(this)); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an * unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {FailedInnerCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert FailedInnerCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/ERC721.sol) pragma solidity ^0.8.20; import {IERC721} from "./IERC721.sol"; import {IERC721Receiver} from "./IERC721Receiver.sol"; import {IERC721Metadata} from "./extensions/IERC721Metadata.sol"; import {Context} from "../../utils/Context.sol"; import {Strings} from "../../utils/Strings.sol"; import {IERC165, ERC165} from "../../utils/introspection/ERC165.sol"; import {IERC721Errors} from "../../interfaces/draft-IERC6093.sol"; /** * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including * the Metadata extension, but not including the Enumerable extension, which is available separately as * {ERC721Enumerable}. */ abstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Errors { using Strings for uint256; // Token name string private _name; // Token symbol string private _symbol; mapping(uint256 tokenId => address) private _owners; mapping(address owner => uint256) private _balances; mapping(uint256 tokenId => address) private _tokenApprovals; mapping(address owner => mapping(address operator => bool)) private _operatorApprovals; /** * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC721).interfaceId || interfaceId == type(IERC721Metadata).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721-balanceOf}. */ function balanceOf(address owner) public view virtual returns (uint256) { if (owner == address(0)) { revert ERC721InvalidOwner(address(0)); } return _balances[owner]; } /** * @dev See {IERC721-ownerOf}. */ function ownerOf(uint256 tokenId) public view virtual returns (address) { return _requireOwned(tokenId); } /** * @dev See {IERC721Metadata-name}. */ function name() public view virtual returns (string memory) { return _name; } /** * @dev See {IERC721Metadata-symbol}. */ function symbol() public view virtual returns (string memory) { return _symbol; } /** * @dev See {IERC721Metadata-tokenURI}. */ function tokenURI(uint256 tokenId) public view virtual returns (string memory) { _requireOwned(tokenId); string memory baseURI = _baseURI(); return bytes(baseURI).length > 0 ? string.concat(baseURI, tokenId.toString()) : ""; } /** * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each * token will be the concatenation of the `baseURI` and the `tokenId`. Empty * by default, can be overridden in child contracts. */ function _baseURI() internal view virtual returns (string memory) { return ""; } /** * @dev See {IERC721-approve}. */ function approve(address to, uint256 tokenId) public virtual { _approve(to, tokenId, _msgSender()); } /** * @dev See {IERC721-getApproved}. */ function getApproved(uint256 tokenId) public view virtual returns (address) { _requireOwned(tokenId); return _getApproved(tokenId); } /** * @dev See {IERC721-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual { _setApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC721-isApprovedForAll}. */ function isApprovedForAll(address owner, address operator) public view virtual returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev See {IERC721-transferFrom}. */ function transferFrom(address from, address to, uint256 tokenId) public virtual { if (to == address(0)) { revert ERC721InvalidReceiver(address(0)); } // Setting an "auth" arguments enables the `_isAuthorized` check which verifies that the token exists // (from != 0). Therefore, it is not needed to verify that the return value is not 0 here. address previousOwner = _update(to, tokenId, _msgSender()); if (previousOwner != from) { revert ERC721IncorrectOwner(from, tokenId, previousOwner); } } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom(address from, address to, uint256 tokenId) public { safeTransferFrom(from, to, tokenId, ""); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual { transferFrom(from, to, tokenId); _checkOnERC721Received(from, to, tokenId, data); } /** * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist * * IMPORTANT: Any overrides to this function that add ownership of tokens not tracked by the * core ERC721 logic MUST be matched with the use of {_increaseBalance} to keep balances * consistent with ownership. The invariant to preserve is that for any address `a` the value returned by * `balanceOf(a)` must be equal to the number of tokens such that `_ownerOf(tokenId)` is `a`. */ function _ownerOf(uint256 tokenId) internal view virtual returns (address) { return _owners[tokenId]; } /** * @dev Returns the approved address for `tokenId`. Returns 0 if `tokenId` is not minted. */ function _getApproved(uint256 tokenId) internal view virtual returns (address) { return _tokenApprovals[tokenId]; } /** * @dev Returns whether `spender` is allowed to manage `owner`'s tokens, or `tokenId` in * particular (ignoring whether it is owned by `owner`). * * WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this * assumption. */ function _isAuthorized(address owner, address spender, uint256 tokenId) internal view virtual returns (bool) { return spender != address(0) && (owner == spender || isApprovedForAll(owner, spender) || _getApproved(tokenId) == spender); } /** * @dev Checks if `spender` can operate on `tokenId`, assuming the provided `owner` is the actual owner. * Reverts if `spender` does not have approval from the provided `owner` for the given token or for all its assets * the `spender` for the specific `tokenId`. * * WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this * assumption. */ function _checkAuthorized(address owner, address spender, uint256 tokenId) internal view virtual { if (!_isAuthorized(owner, spender, tokenId)) { if (owner == address(0)) { revert ERC721NonexistentToken(tokenId); } else { revert ERC721InsufficientApproval(spender, tokenId); } } } /** * @dev Unsafe write access to the balances, used by extensions that "mint" tokens using an {ownerOf} override. * * NOTE: the value is limited to type(uint128).max. This protect against _balance overflow. It is unrealistic that * a uint256 would ever overflow from increments when these increments are bounded to uint128 values. * * WARNING: Increasing an account's balance using this function tends to be paired with an override of the * {_ownerOf} function to resolve the ownership of the corresponding tokens so that balances and ownership * remain consistent with one another. */ function _increaseBalance(address account, uint128 value) internal virtual { unchecked { _balances[account] += value; } } /** * @dev Transfers `tokenId` from its current owner to `to`, or alternatively mints (or burns) if the current owner * (or `to`) is the zero address. Returns the owner of the `tokenId` before the update. * * The `auth` argument is optional. If the value passed is non 0, then this function will check that * `auth` is either the owner of the token, or approved to operate on the token (by the owner). * * Emits a {Transfer} event. * * NOTE: If overriding this function in a way that tracks balances, see also {_increaseBalance}. */ function _update(address to, uint256 tokenId, address auth) internal virtual returns (address) { address from = _ownerOf(tokenId); // Perform (optional) operator check if (auth != address(0)) { _checkAuthorized(from, auth, tokenId); } // Execute the update if (from != address(0)) { // Clear approval. No need to re-authorize or emit the Approval event _approve(address(0), tokenId, address(0), false); unchecked { _balances[from] -= 1; } } if (to != address(0)) { unchecked { _balances[to] += 1; } } _owners[tokenId] = to; emit Transfer(from, to, tokenId); return from; } /** * @dev Mints `tokenId` and transfers it to `to`. * * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible * * Requirements: * * - `tokenId` must not exist. * - `to` cannot be the zero address. * * Emits a {Transfer} event. */ function _mint(address to, uint256 tokenId) internal { if (to == address(0)) { revert ERC721InvalidReceiver(address(0)); } address previousOwner = _update(to, tokenId, address(0)); if (previousOwner != address(0)) { revert ERC721InvalidSender(address(0)); } } /** * @dev Mints `tokenId`, transfers it to `to` and checks for `to` acceptance. * * Requirements: * * - `tokenId` must not exist. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeMint(address to, uint256 tokenId) internal { _safeMint(to, tokenId, ""); } /** * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is * forwarded in {IERC721Receiver-onERC721Received} to contract recipients. */ function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual { _mint(to, tokenId); _checkOnERC721Received(address(0), to, tokenId, data); } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * This is an internal function that does not check if the sender is authorized to operate on the token. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function _burn(uint256 tokenId) internal { address previousOwner = _update(address(0), tokenId, address(0)); if (previousOwner == address(0)) { revert ERC721NonexistentToken(tokenId); } } /** * @dev Transfers `tokenId` from `from` to `to`. * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. * * Requirements: * * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * * Emits a {Transfer} event. */ function _transfer(address from, address to, uint256 tokenId) internal { if (to == address(0)) { revert ERC721InvalidReceiver(address(0)); } address previousOwner = _update(to, tokenId, address(0)); if (previousOwner == address(0)) { revert ERC721NonexistentToken(tokenId); } else if (previousOwner != from) { revert ERC721IncorrectOwner(from, tokenId, previousOwner); } } /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking that contract recipients * are aware of the ERC721 standard to prevent tokens from being forever locked. * * `data` is additional data, it has no specified format and it is sent in call to `to`. * * This internal function is like {safeTransferFrom} in the sense that it invokes * {IERC721Receiver-onERC721Received} on the receiver, and can be used to e.g. * implement alternative mechanisms to perform token transfer, such as signature-based. * * Requirements: * * - `tokenId` token must exist and be owned by `from`. * - `to` cannot be the zero address. * - `from` cannot be the zero address. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeTransfer(address from, address to, uint256 tokenId) internal { _safeTransfer(from, to, tokenId, ""); } /** * @dev Same as {xref-ERC721-_safeTransfer-address-address-uint256-}[`_safeTransfer`], with an additional `data` parameter which is * forwarded in {IERC721Receiver-onERC721Received} to contract recipients. */ function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual { _transfer(from, to, tokenId); _checkOnERC721Received(from, to, tokenId, data); } /** * @dev Approve `to` to operate on `tokenId` * * The `auth` argument is optional. If the value passed is non 0, then this function will check that `auth` is * either the owner of the token, or approved to operate on all tokens held by this owner. * * Emits an {Approval} event. * * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument. */ function _approve(address to, uint256 tokenId, address auth) internal { _approve(to, tokenId, auth, true); } /** * @dev Variant of `_approve` with an optional flag to enable or disable the {Approval} event. The event is not * emitted in the context of transfers. */ function _approve(address to, uint256 tokenId, address auth, bool emitEvent) internal virtual { // Avoid reading the owner unless necessary if (emitEvent || auth != address(0)) { address owner = _requireOwned(tokenId); // We do not use _isAuthorized because single-token approvals should not be able to call approve if (auth != address(0) && owner != auth && !isApprovedForAll(owner, auth)) { revert ERC721InvalidApprover(auth); } if (emitEvent) { emit Approval(owner, to, tokenId); } } _tokenApprovals[tokenId] = to; } /** * @dev Approve `operator` to operate on all of `owner` tokens * * Requirements: * - operator can't be the address zero. * * Emits an {ApprovalForAll} event. */ function _setApprovalForAll(address owner, address operator, bool approved) internal virtual { if (operator == address(0)) { revert ERC721InvalidOperator(operator); } _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @dev Reverts if the `tokenId` doesn't have a current owner (it hasn't been minted, or it has been burned). * Returns the owner. * * Overrides to ownership logic should be done to {_ownerOf}. */ function _requireOwned(uint256 tokenId) internal view returns (address) { address owner = _ownerOf(tokenId); if (owner == address(0)) { revert ERC721NonexistentToken(tokenId); } return owner; } /** * @dev Private function to invoke {IERC721Receiver-onERC721Received} on a target address. This will revert if the * recipient doesn't accept the token transfer. The call is not executed if the target address is not a contract. * * @param from address representing the previous owner of the given token ID * @param to target address that will receive the tokens * @param tokenId uint256 ID of the token to be transferred * @param data bytes optional data to send along with the call */ function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory data) private { if (to.code.length > 0) { try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) { if (retval != IERC721Receiver.onERC721Received.selector) { revert ERC721InvalidReceiver(to); } } catch (bytes memory reason) { if (reason.length == 0) { revert ERC721InvalidReceiver(to); } else { /// @solidity memory-safe-assembly assembly { revert(add(32, reason), mload(reason)) } } } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.20; import {IERC165} from "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon * a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or * {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon * a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721 * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must * understand this adds an external call which potentially creates a reentrancy vulnerability. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 tokenId) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the address zero. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); }
// 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 // OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol) pragma solidity ^0.8.20; import {Math} from "./math/Math.sol"; import {SignedMath} from "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant HEX_DIGITS = "0123456789abcdef"; uint8 private constant ADDRESS_LENGTH = 20; /** * @dev The `value` string doesn't fit in the specified `length`. */ error StringsInsufficientHexLength(uint256 value, uint256 length); /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), HEX_DIGITS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toStringSigned(int256 value) internal pure returns (string memory) { return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { uint256 localValue = value; bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = HEX_DIGITS[localValue & 0xf]; localValue >>= 4; } if (localValue != 0) { revert StringsInsufficientHexLength(value, length); } return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal * representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b)); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.4; interface BNS { // 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; 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 {ResolverBase} from "src/resolver/types/ResolverBase.sol"; import {IABIResolver} from "src/resolver/interfaces/IABIResolver.sol"; abstract contract ABIResolver is IABIResolver, ResolverBase { mapping(uint64 => mapping(bytes32 => mapping(uint256 => bytes))) versionable_abis; /** * Sets the ABI associated with an BNS 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 BNS node. * Defined in EIP205. * @param node The BNS 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} from "src/resolver/types/ResolverBase.sol"; import "src/resolver/interfaces/IAddrResolver.sol"; import "src/resolver/interfaces/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 BNS node. * May only be called by the owner of that node in the BNS 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 BNS node. * @param node The BNS 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} from "src/resolver/types/ResolverBase.sol"; import "src/resolver/interfaces/IContentHashResolver.sol"; abstract contract ContentHashResolver is IContentHashResolver, ResolverBase { mapping(uint64 => mapping(bytes32 => bytes)) versionable_hashes; /** * Sets the contenthash associated with an BNS node. * May only be called by the owner of that node in the BNS 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 BNS node. * @param node The BNS 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; 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; import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import {ResolverBase} from "src/resolver/types/ResolverBase.sol"; import {AddrResolver} from "src/resolver/profiles/AddrResolver.sol"; import {IInterfaceResolver} from "src/resolver/interfaces/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 BNS 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 "@openzeppelin/contracts/utils/introspection/ERC165.sol"; // Internal imports import "src/resolver/interfaces/IMulticallable.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]); if (!success) { if (result.length > 0) { assembly { let revertDataSize := mload(result) revert(add(result, 32), revertDataSize) } } else { revert("Multicall delegatecall failed without a reason"); } } 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; import {ResolverBase} from "src/resolver/types/ResolverBase.sol"; import "src/resolver/interfaces/INameResolver.sol"; abstract contract NameResolver is INameResolver, ResolverBase { mapping(uint64 => mapping(bytes32 => string)) versionable_names; /** * Sets the name associated with an BNS node, for reverse records. * May only be called by the owner of that node in the BNS 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 BNS node, for reverse records. * Defined in EIP181. * @param node The BNS 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} from "src/resolver/types/ResolverBase.sol"; import "src/resolver/interfaces/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 BNS node. * @param node The BNS 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 BNS node. * Defined in EIP 619. * @param node The BNS 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} from "src/resolver/types/ResolverBase.sol"; import "src/resolver/interfaces/ITextResolver.sol"; abstract contract TextResolver is ITextResolver, ResolverBase { mapping(uint64 => mapping(bytes32 => mapping(string => string))) versionable_texts; /** * Sets the text data associated with an BNS node and key. * May only be called by the owner of that node in the BNS 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 BNS node and key. * @param node The BNS 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 // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.20; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be * reverted. * * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/IERC721Metadata.sol) pragma solidity ^0.8.20; import {IERC721} from "../IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Metadata is IERC721 { /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol) pragma solidity ^0.8.20; /** * @dev Standard ERC20 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens. */ interface IERC20Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC20InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC20InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers. * @param spender Address that may be allowed to operate on tokens without being their owner. * @param allowance Amount of tokens a `spender` is allowed to operate with. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC20InvalidApprover(address approver); /** * @dev Indicates a failure with the `spender` to be approved. Used in approvals. * @param spender Address that may be allowed to operate on tokens without being their owner. */ error ERC20InvalidSpender(address spender); } /** * @dev Standard ERC721 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens. */ interface IERC721Errors { /** * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20. * Used in balance queries. * @param owner Address of the current owner of a token. */ error ERC721InvalidOwner(address owner); /** * @dev Indicates a `tokenId` whose `owner` is the zero address. * @param tokenId Identifier number of a token. */ error ERC721NonexistentToken(uint256 tokenId); /** * @dev Indicates an error related to the ownership over a particular token. Used in transfers. * @param sender Address whose tokens are being transferred. * @param tokenId Identifier number of a token. * @param owner Address of the current owner of a token. */ error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC721InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC721InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param tokenId Identifier number of a token. */ error ERC721InsufficientApproval(address operator, uint256 tokenId); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC721InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC721InvalidOperator(address operator); } /** * @dev Standard ERC1155 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens. */ interface IERC1155Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. * @param tokenId Identifier number of a token. */ error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC1155InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC1155InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param owner Address of the current owner of a token. */ error ERC1155MissingApprovalForAll(address operator, address owner); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC1155InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC1155InvalidOperator(address operator); /** * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. * Used in batch transfers. * @param idsLength Length of the array of token identifiers * @param valuesLength Length of the array of token amounts */ error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength); }
// 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 // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol) pragma solidity ^0.8.20; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Muldiv operation overflow. */ error MathOverflowedMulDiv(); enum Rounding { Floor, // Toward negative infinity Ceil, // Toward positive infinity Trunc, // Toward zero Expand // Away from zero } /** * @dev Returns the addition of two unsigned integers, with an overflow flag. */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds towards infinity instead * of rounding towards zero. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { if (b == 0) { // Guarantee the same behavior as in a regular Solidity division. return a / b; } // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or * denominator == 0. * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by * Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0 = x * y; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. if (denominator <= prod1) { revert MathOverflowedMulDiv(); } /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. // Always >= 1. See https://cs.stackexchange.com/q/138556/92363. uint256 twos = denominator & (0 - denominator); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also // works in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded * towards zero. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256 of a positive value rounded towards zero. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0); } } /** * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers. */ function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { return uint8(rounding) % 2 == 1; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.20; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.4; import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; import {IVersionableResolver} from "src/resolver/interfaces/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), "Unauthorized"); _; } /** * Increments the record version associated with an BNS node. * May only be called by the owner of that node in the BNS 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 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; /** * Interface for the legacy (ETH-only) addr function. */ interface IAddrResolver { event AddrChanged(bytes32 indexed node, address a); /** * Returns the address associated with an BNS node. * @param node The BNS 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 BNS node. * @param node The BNS node to query. * @return The associated contenthash. */ function contenthash(bytes32 node) external view returns (bytes memory); }
// 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 BNS 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 pragma solidity >=0.8.4; interface INameResolver { event NameChanged(bytes32 indexed node, string name); /** * Returns the name associated with an BNS node, for reverse records. * Defined in EIP181. * @param node The BNS node to query. * @return The associated name. */ function name(bytes32 node) external view returns (string memory); } abstract contract AbstractNameResolver { function setName(bytes32 node, string memory name) public virtual; }
// 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 BNS node and key. * @param node The BNS 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); }
{ "remappings": [ "@pythnetwork/pyth-sdk-solidity/=node_modules/@pythnetwork/pyth-sdk-solidity/", "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "forge-std/=lib/forge-std/src/", "ds-test/=lib/openzeppelin-contracts/lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", "openzeppelin-contracts/=lib/openzeppelin-contracts/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "evmVersion": "cancun", "viaIR": false, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract BaseRegistrar","name":"base_","type":"address"},{"internalType":"contract IPriceOracle","name":"prices_","type":"address"},{"internalType":"contract IReverseRegistrar","name":"reverseRegistrar_","type":"address"},{"internalType":"address","name":"whitelistSigner_","type":"address"},{"internalType":"address","name":"freeWhitelistSigner_","type":"address"},{"internalType":"contract IReservedRegistry","name":"reservedRegistry_","type":"address"},{"internalType":"address","name":"owner_","type":"address"},{"internalType":"bytes32","name":"rootNode_","type":"bytes32"},{"internalType":"string","name":"rootName_","type":"string"},{"internalType":"address","name":"paymentReceiver_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"CantSetReverseRecordForOthers","type":"error"},{"inputs":[{"internalType":"uint256","name":"duration","type":"uint256"}],"name":"DurationTooShort","type":"error"},{"inputs":[],"name":"ECDSAInvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"ECDSAInvalidSignatureLength","type":"error"},{"inputs":[{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ECDSAInvalidSignatureS","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"FreeMintLimitReached","type":"error"},{"inputs":[],"name":"FreeMintSignatureAlreadyUsed","type":"error"},{"inputs":[],"name":"InsufficientValue","type":"error"},{"inputs":[],"name":"InvalidFreeWhitelistSigner","type":"error"},{"inputs":[],"name":"InvalidPaymentReceiver","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"InvalidUTF8Byte","type":"error"},{"inputs":[],"name":"InvalidWhitelistSigner","type":"error"},{"inputs":[],"name":"LaunchTimeInPast","type":"error"},{"inputs":[],"name":"MintLimitForRoundReached","type":"error"},{"inputs":[{"internalType":"string","name":"name","type":"string"}],"name":"NameNotAvailable","type":"error"},{"inputs":[],"name":"NameNotReserved","type":"error"},{"inputs":[],"name":"NameReserved","type":"error"},{"inputs":[],"name":"NotAuthorisedToMintReservedNames","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"PublicSaleNotLive","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[],"name":"ResolverRequiredWhenDataSupplied","type":"error"},{"inputs":[],"name":"ReverseRecordNotAllowedForReservedNames","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"SignatureAlreadyUsed","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"payee","type":"address"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"}],"name":"ETHPaymentProcessed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newFreeWhitelistAuthorizerAddress","type":"address"}],"name":"FreeWhitelistAuthorizerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newLaunchTime","type":"uint256"}],"name":"LaunchTimeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":true,"internalType":"bytes32","name":"label","type":"bytes32"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"expires","type":"uint256"}],"name":"NameRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":true,"internalType":"bytes32","name":"label","type":"bytes32"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"referral","type":"address"},{"indexed":false,"internalType":"uint256","name":"expires","type":"uint256"}],"name":"NameRegisteredWithReferral","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":true,"internalType":"bytes32","name":"label","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"expires","type":"uint256"}],"name":"NameRenewed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newPaymentReceiver","type":"address"}],"name":"PaymentReceiverUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newPrices","type":"address"}],"name":"PriceOracleUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newReservedNameMinterAddress","type":"address"}],"name":"ReservedNamesMinterChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newReverseRegistrar","type":"address"}],"name":"ReverseRegistrarUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newWhitelistAuthorizerAddress","type":"address"}],"name":"WhitelistAuthorizerChanged","type":"event"},{"inputs":[],"name":"MIN_NAME_LENGTH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_REGISTRATION_DURATION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"name","type":"string"}],"name":"available","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"freeMintsByAddress","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFreeWhitelistAuthorizer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReservedNamesMinter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWhitelistAuthorizer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"launchTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"mintsCountByRoundByAddress","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paymentReceiver","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"prices","outputs":[{"internalType":"contract IPriceOracle","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"recoverFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"address","name":"resolver","type":"address"},{"internalType":"bytes[]","name":"data","type":"bytes[]"},{"internalType":"bool","name":"reverseRecord","type":"bool"},{"internalType":"address","name":"referrer","type":"address"}],"internalType":"struct RegistrarController.RegisterRequest","name":"request","type":"tuple"}],"name":"register","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"duration","type":"uint256"}],"name":"registerPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"duration","type":"uint256"}],"name":"renew","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"duration","type":"uint256"}],"name":"rentPrice","outputs":[{"components":[{"internalType":"uint256","name":"base","type":"uint256"},{"internalType":"uint256","name":"discount","type":"uint256"}],"internalType":"struct IPriceOracle.Price","name":"price","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"address","name":"resolver","type":"address"},{"internalType":"bytes[]","name":"data","type":"bytes[]"},{"internalType":"bool","name":"reverseRecord","type":"bool"},{"internalType":"address","name":"referrer","type":"address"}],"internalType":"struct RegistrarController.RegisterRequest","name":"request","type":"tuple"}],"name":"reservedRegister","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"reservedRegistry","outputs":[{"internalType":"contract IReservedRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"reverseRegistrar","outputs":[{"internalType":"contract IReverseRegistrar","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rootName","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rootNode","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_freeWhitelistAuthorizer","type":"address"}],"name":"setFreeWhitelistAuthorizer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"launchTime_","type":"uint256"}],"name":"setLaunchTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"paymentReceiver_","type":"address"}],"name":"setPaymentReceiver","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IPriceOracle","name":"prices_","type":"address"}],"name":"setPriceOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"reservedNamesMinter_","type":"address"}],"name":"setReservedNamesMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IReverseRegistrar","name":"reverse_","type":"address"}],"name":"setReverseRegistrar","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_whitelistAuthorizer","type":"address"}],"name":"setWhitelistAuthorizer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"usedFreeMintsSignatures","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"usedSignatures","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"name","type":"string"}],"name":"valid","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"address","name":"resolver","type":"address"},{"internalType":"bytes[]","name":"data","type":"bytes[]"},{"internalType":"bool","name":"reverseRecord","type":"bool"},{"internalType":"address","name":"referrer","type":"address"}],"internalType":"struct RegistrarController.RegisterRequest","name":"request","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"whitelistFreeRegister","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"address","name":"resolver","type":"address"},{"internalType":"bytes[]","name":"data","type":"bytes[]"},{"internalType":"bool","name":"reverseRecord","type":"bool"},{"internalType":"address","name":"referrer","type":"address"}],"internalType":"struct RegistrarController.RegisterRequest","name":"registerRequest","type":"tuple"},{"internalType":"uint256","name":"round_id","type":"uint256"},{"internalType":"uint256","name":"round_total_mint","type":"uint256"}],"internalType":"struct RegistrarController.WhitelistRegisterRequest","name":"request","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"whitelistRegister","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"withdrawETH","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60c060405234801561000f575f5ffd5b50604051613a25380380613a2583398101604081905261002e916102ec565b836001600160a01b03811661005c57604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b610065816101d9565b50600180556001600160a01b038a8116608052600280546001600160a01b03199081168c841617909155600380549091168a831617905587166100bb57604051633a504b8760e01b815260040160405180910390fd5b600c80546001600160a01b0319166001600160a01b038981169190911790915586166100fa57604051635897283760e11b815260040160405180910390fd5b600d80546001600160a01b0319166001600160a01b03881617905560a083905260056101268382610442565b50600680546001600160a01b038084166001600160a01b031992831617909255600480548884169216919091178155600354604051630f41a04d60e11b8152921691631e83409a91610189918891016001600160a01b0391909116815260200190565b6020604051808303815f875af11580156101a5573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101c991906104fc565b5050505050505050505050610513565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b038116811461023c575f5ffd5b50565b805161024a81610228565b919050565b634e487b7160e01b5f52604160045260245ffd5b5f82601f830112610272575f5ffd5b81516001600160401b0381111561028b5761028b61024f565b604051601f8201601f19908116603f011681016001600160401b03811182821017156102b9576102b961024f565b6040528181528382016020018510156102d0575f5ffd5b8160208501602083015e5f918101602001919091529392505050565b5f5f5f5f5f5f5f5f5f5f6101408b8d031215610306575f5ffd5b8a5161031181610228565b60208c0151909a5061032281610228565b60408c015190995061033381610228565b60608c015190985061034481610228565b965061035260808c0161023f565b955061036060a08c0161023f565b945061036e60c08c0161023f565b60e08c01516101008d015191955093506001600160401b03811115610391575f5ffd5b61039d8d828e01610263565b9250506103ad6101208c0161023f565b90509295989b9194979a5092959850565b600181811c908216806103d257607f821691505b6020821081036103f057634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111561043d57805f5260205f20601f840160051c8101602085101561041b5750805b601f840160051c820191505b8181101561043a575f8155600101610427565b50505b505050565b81516001600160401b0381111561045b5761045b61024f565b61046f8161046984546103be565b846103f6565b6020601f8211600181146104a1575f831561048a5750848201515b5f19600385901b1c1916600184901b17845561043a565b5f84815260208120601f198516915b828110156104d057878501518255602094850194600190920191016104b0565b50848210156104ed57868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b5f6020828403121561050c575f5ffd5b5051919050565b60805160a0516134d56105505f395f81816106cf015261263f01525f8181610aba01528181610bab015281816112320152611a7001526134d55ff3fe608060405260043610610212575f3560e01c80638da5cb5b1161011e578063d3419bf3116100a8578063eeb144da1161006d578063eeb144da1461063d578063f20387df14610650578063f2fde38b14610671578063f978fd6114610690578063faff50a8146106be575f5ffd5b8063d3419bf3146105ad578063d57a11f1146105cc578063dc7daea3146105eb578063e086e5ec1461060a578063e72c1e551461061e575f5ffd5b8063aeb8ce9b116100ee578063aeb8ce9b1461051e578063b36c3be81461053d578063bf80668414610550578063cb37f3b21461056f578063d2ff3bdc1461058e575f5ffd5b80638da5cb5b146104b15780639791c097146104cd5780639ff46e74146104ec578063acf1a8411461050b575f5ffd5b80635d3590d51161019f578063790ca4131161016f578063790ca4131461040f5780637c127a9614610424578063808698531461044157806383e7f6ff146104605780638a95b09f1461049a575f5ffd5b80635d3590d51461037d5780635f17e2651461039c57806365ebf99a146103dc578063715018a6146103fb575f5ffd5b806350cfeddd116101e557806350cfeddd146102ce578063530e784f146102e257806354826fe714610301578063557499ba1461033f5780635829831d1461035e575f5ffd5b8063010adc4d146102165780630495a8441461024c57806313d56a9c14610269578063501b3fd71461028a575b5f5ffd5b348015610221575f5ffd5b50600d546001600160a01b03165b6040516001600160a01b0390911681526020015b60405180910390f35b348015610257575f5ffd5b50600b546001600160a01b031661022f565b348015610274575f5ffd5b50610288610283366004612ac7565b6106f1565b005b348015610295575f5ffd5b506102c06102a4366004612ae2565b600960209081525f928352604080842090915290825290205481565b604051908152602001610243565b3480156102d9575f5ffd5b506102c0600181565b3480156102ed575f5ffd5b506102886102fc366004612ac7565b61074e565b34801561030c575f5ffd5b5061032f61031b366004612b0c565b60086020525f908152604090205460ff1681565b6040519015158152602001610243565b34801561034a575f5ffd5b50610288610359366004612ac7565b6107a4565b348015610369575f5ffd5b50610288610378366004612ac7565b6107fa565b348015610388575f5ffd5b50610288610397366004612b23565b610850565b3480156103a7575f5ffd5b506103ca6103b6366004612ac7565b600e6020525f908152604090205460ff1681565b60405160ff9091168152602001610243565b3480156103e7575f5ffd5b506102886103f6366004612ac7565b610871565b348015610406575f5ffd5b506102886108ee565b34801561041a575f5ffd5b506102c0600a5481565b34801561042f575f5ffd5b50600c546001600160a01b031661022f565b34801561044c575f5ffd5b5060035461022f906001600160a01b031681565b34801561046b575f5ffd5b5061047f61047a366004612c1d565b610901565b60408051825181526020928301519281019290925201610243565b3480156104a5575f5ffd5b506102c06301e1338081565b3480156104bc575f5ffd5b505f546001600160a01b031661022f565b3480156104d8575f5ffd5b5061032f6104e7366004612c5e565b61099b565b3480156104f7575f5ffd5b50610288610506366004612b0c565b6109d6565b610288610519366004612cd3565b610a34565b348015610529575f5ffd5b5061032f610538366004612c5e565b610b7c565b61028861054b366004612d1a565b610c23565b34801561055b575f5ffd5b5061028861056a366004612ac7565b610c52565b34801561057a575f5ffd5b5060065461022f906001600160a01b031681565b348015610599575f5ffd5b5060045461022f906001600160a01b031681565b3480156105b8575f5ffd5b5060025461022f906001600160a01b031681565b3480156105d7575f5ffd5b506102886105e6366004612d9b565b610ca8565b3480156105f6575f5ffd5b50610288610605366004612de9565b610e22565b348015610615575f5ffd5b50610288610fb9565b348015610629575f5ffd5b506102c0610638366004612c1d565b61102d565b61028861064b366004612de9565b611052565b34801561065b575f5ffd5b50610664611087565b6040516102439190612e48565b34801561067c575f5ffd5b5061028861068b366004612ac7565b611113565b34801561069b575f5ffd5b5061032f6106aa366004612b0c565b60076020525f908152604090205460ff1681565b3480156106c9575f5ffd5b506102c07f000000000000000000000000000000000000000000000000000000000000000081565b6106f961114d565b600c80546001600160a01b0319166001600160a01b0383169081179091556040519081527f63651f54b104da052b16eb4d518afa4c0b1f6d2b77b9ab0f445787585234de37906020015b60405180910390a150565b61075661114d565b600280546001600160a01b0319166001600160a01b0383169081179091556040519081527fefe8ab924ca486283a79dc604baa67add51afb82af1db8ac386ebbba643cdffd90602001610743565b6107ac61114d565b600380546001600160a01b0319166001600160a01b0383169081179091556040519081527fd192c0b229b00473ccb6ccfebf6642805bca1dcdf2d9fb4fd102c7dc7ea4ce2390602001610743565b61080261114d565b600b80546001600160a01b0319166001600160a01b0383169081179091556040519081527f1c8833ad9579b88233573f0b91eb8ab86e24450f9e11151c6387dff4d5b4f61a90602001610743565b61085861114d565b61086c6001600160a01b0384168383611179565b505050565b61087961114d565b6001600160a01b0381166108a0576040516301ed76a760e61b815260040160405180910390fd5b600680546001600160a01b0319166001600160a01b0383169081179091556040519081527f6cfddd24d2afc1b9f31d51f0ef77029fdde044799f0a87a2a09b7673b609742290602001610743565b6108f661114d565b6108ff5f6111cb565b565b604080518082019091525f8082526020820152825160208401206002546001600160a01b03166350e9a715856109368461121a565b866040518463ffffffff1660e01b815260040161095593929190612e5a565b6040805180830381865afa15801561096f573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109939190612e7e565b949350505050565b5f5f6109a5835190565b90505f6109b1846112c1565b90505f8211801561099357506001811480156109cd5750600182115b15949350505050565b6109de61114d565b428110156109ff5760405163f7235ed760e01b815260040160405180910390fd5b600a8190556040518181527fdb5fc205901030b15dae0c28aeedbdf381585f7e12f86855899a3b5328aa34e990602001610743565b5f8383604051610a45929190612ecc565b604080519182900382206020601f8701819004810284018101909252858352925082915f91610a90919088908890819084018382808284375f9201919091525088925061102d915050565b9050610a9b81611411565b60405163c475abff60e01b815260048101839052602481018590525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c475abff906044016020604051808303815f875af1158015610b08573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b2c9190612edb565b9050610b378261146a565b837f93bc1a84707231b1d9552157299797c64a1a8c5bc79f05153716630c9c4936fc888884604051610b6b93929190612f1a565b60405180910390a250505050505050565b805160208201205f90610b8e8361099b565b8015610c1c5750604051633a178d9960e01b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633a178d9990602401602060405180830381865afa158015610bf8573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c1c9190612f4a565b9392505050565b610c2e8383836114f1565b610c40610c3b8480612f65565b6116e3565b61086c610c4d8480612f65565b6117c9565b610c5a61114d565b600d80546001600160a01b0319166001600160a01b0383169081179091556040519081527f3639a5ccd808ae1a86d60a5b738cd981061b7478ad45ae0b2aea54994938022b90602001610743565b825f610cb76080830183612f83565b9050118015610cdd57505f610cd26080830160608401612ac7565b6001600160a01b0316145b15610cfb576040516334fd817160e21b815260040160405180910390fd5b610d41610d088280612fc8565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610b7c92505050565b610d7357610d4f8180612fc8565b6040516308eee0fd60e31b8152600401610d6a92919061300a565b60405180910390fd5b6301e1338081604001351015610da25760408051639a71997b60e01b8152908201356004820152602401610d6a565b610dad8484846118ce565b5f610df4610dbb8680612fc8565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506112c192505050565b90506003811015610e0957610d4f8580612fc8565b610e12856116e3565b610e1b85611a65565b5050505050565b805f610e316080830183612f83565b9050118015610e5757505f610e4c6080830160608401612ac7565b6001600160a01b0316145b15610e75576040516334fd817160e21b815260040160405180910390fd5b610e82610d088280612fc8565b610e9057610d4f8180612fc8565b6301e1338081604001351015610ebf5760408051639a71997b60e01b8152908201356004820152602401610d6a565b600b546001600160a01b03163314610eea5760405163e0d1f21760e01b815260040160405180910390fd5b6004546001600160a01b0316631c40a2ac610f058480612fc8565b6040518363ffffffff1660e01b8152600401610f2292919061300a565b602060405180830381865afa158015610f3d573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f619190612f4a565b610f7e57604051637d6fe8d760e11b815260040160405180910390fd5b610f8e60c0830160a0840161301d565b15610fac5760405163b1a5a8ef60e01b815260040160405180910390fd5b610fb582611a65565b5050565b6006546040515f916001600160a01b03169047908381818185875af1925050503d805f8114611003576040519150601f19603f3d011682016040523d82523d5f602084013e611008565b606091505b505090508061102a576040516312171d8360e31b815260040160405180910390fd5b50565b5f5f6110398484610901565b602081015181519192506109939161304c565b92915050565b600a544210156110755760405163a9f4f87160e01b815260040160405180910390fd5b61107e816116e3565b61102a816117c9565b600580546110949061305f565b80601f01602080910402602001604051908101604052809291908181526020018280546110c09061305f565b801561110b5780601f106110e25761010080835404028352916020019161110b565b820191905f5260205f20905b8154815290600101906020018083116110ee57829003601f168201915b505050505081565b61111b61114d565b6001600160a01b03811661114457604051631e4fbdf760e01b81525f6004820152602401610d6a565b61102a816111cb565b5f546001600160a01b031633146108ff5760405163118cdaa760e01b8152336004820152602401610d6a565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261086c908490611d60565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60405163727e4ea760e01b8152600481018290525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063727e4ea790602401602060405180830381865afa15801561127f573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112a39190612edb565b9050805f036112b4575050600a5490565b61104c62278d0082613091565b80515f908290829081905b80821015611407575f6112df8584611dc1565b90505f6112ec8285613091565b90505b828110801561130357506113038682611ff1565b15611323576113128682611dc1565b61131c9082613091565b90506112ef565b8281108015611337575061133786826123fb565b156113ae576113468682611dc1565b6113509082613091565b9050828110156113ae575f6113658783611dc1565b90506113718183613091565b91505b838210801561138857506113888783611ff1565b156113a8576113978783611dc1565b6113a19083613091565b9150611374565b50611323565b6113b886856124b4565b80156113c357508281105b80156113d457506113d486826124b4565b156113f0576113e38682611dc1565b6113ed9082613091565b90505b846113fa816130a4565b95505080935050506112cc565b5090949350505050565b803410156114325760405163044044a560e21b815260040160405180910390fd5b60405181815233907fbc769889246686134856b409155bb87630ea5797a705fa98b61f576d316aab9b9060200160405180910390a250565b61147261256d565b803411156114e8575f33611486833461304c565b6040515f81818185875af1925050503d805f81146114bf576040519150601f19603f3d011682016040523d82523d5f602084013e6114c4565b606091505b50509050806114e6576040516312171d8360e31b815260040160405180910390fd5b505b61102a60018055565b5f6114fc8480612f65565b6115069080612fc8565b6115108680612f65565b611521906040810190602001612ac7565b61152b8780612f65565b604001356115398880612f65565b61154a906080810190606001612ac7565b6115548980612f65565b611562906080810190612f83565b61156c8b80612f65565b61157d9060c081019060a00161301d565b6115878c80612f65565b6115989060e081019060c001612ac7565b8c602001358d604001356040516020016115bc9b9a99989796959493929190613150565b60405160208183030381529060405290505f6115d782612597565b5f8181526007602052604090205490915060ff16156116095760405163900bb2c960e01b815260040160405180910390fd5b335f9081526009602090815260408083208289013584529091529081902054908601351161164a5760405163771a50b360e01b815260040160405180910390fd5b5f6116568286866125f9565b90506001600160a01b038116158061167c5750600c546001600160a01b03828116911614155b1561169a57604051638baa579f60e01b815260040160405180910390fd5b5f828152600760209081526040808320805460ff191660011790553383526009825280832089830135845290915281208054916116d6836130a4565b9190505550505050505050565b6004546001600160a01b0316631c40a2ac6116fe8380612fc8565b6040518363ffffffff1660e01b815260040161171b92919061300a565b602060405180830381865afa158015611736573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061175a9190612f4a565b1561177857604051632bbd1e6760e11b815260040160405180910390fd5b336117896040830160208401612ac7565b6001600160a01b0316141580156117ab57506117ab60c0820160a0830161301d565b1561102a57604051636eb6599d60e01b815260040160405180910390fd5b805f6117d86080830183612f83565b90501180156117fe57505f6117f36080830160608401612ac7565b6001600160a01b0316145b1561181c576040516334fd817160e21b815260040160405180910390fd5b611829610d088280612fc8565b61183757610d4f8180612fc8565b6301e13380816040013510156118665760408051639a71997b60e01b8152908201356004820152602401610d6a565b5f6118b16118748480612fc8565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250505050604085013561102d565b90506118bc81611411565b6118c583611a65565b61086c8161146a565b5f6118d98480612fc8565b6118e96040870160208801612ac7565b60408701356118fe6080890160608a01612ac7565b61190b60808a018a612f83565b61191b60c08c0160a08d0161301d565b61192b60e08d0160c08e01612ac7565b604051602001611943999897969594939291906131cb565b60405160208183030381529060405290505f61195e82612597565b5f8181526008602052604090205490915060ff161561199057604051633d47d82360e01b815260040160405180910390fd5b335f908152600e602052604090205460ff16156119c05760405163113d0d3f60e11b815260040160405180910390fd5b5f6119cc8286866125f9565b90506001600160a01b03811615806119f25750600d546001600160a01b03828116911614155b15611a1057604051638baa579f60e01b815260040160405180910390fd5b5f828152600860209081526040808320805460ff19166001179055338352600e9091528120805460ff1691611a4483613236565b91906101000a81548160ff021916908360ff16021790555050505050505050565b5f6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663eac2aa09611a9f8480612fc8565b604051611aad929190612ecc565b604080519182900390912090611ac890860160208701612ac7565b6040860135611add6080880160608901612ac7565b6040516001600160e01b031960e087901b16815260048101949094526001600160a01b03928316602485015260448401919091521660648201525f608482015260a4016020604051808303815f875af1158015611b3c573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b609190612edb565b90505f611b706080840184612f83565b90501115611bbe57611bbe611b8b6080840160608501612ac7565b611b958480612fc8565b604051611ba3929190612ecc565b604051908190039020611bb96080860186612f83565b612639565b611bce60c0830160a0840161301d565b15611c2a57611c2a611be08380612fc8565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611c24925050506080850160608601612ac7565b336126fe565b611c3a6040830160208401612ac7565b6001600160a01b0316611c4d8380612fc8565b604051611c5b929190612ecc565b6040519081900390207f0667086d08417333ce63f40d5bc2ef6fd330e25aaaf317b7c489541f8fe600fa611c8f8580612fc8565b85604051611c9f93929190612f1a565b60405180910390a35f611cb860e0840160c08501612ac7565b6001600160a01b031614610fb557611cd660e0830160c08401612ac7565b6001600160a01b0316611cef6040840160208501612ac7565b6001600160a01b0316611d028480612fc8565b604051611d10929190612ecc565b6040519081900390207f1124fcbf46055234a873086b844a44635d54b982d7b4ca7e1631d51a7950e665611d448680612fc8565b86604051611d5493929190612f1a565b60405180910390a45050565b5f611d746001600160a01b038416836127a1565b905080515f14158015611d98575080806020019051810190611d969190612f4a565b155b1561086c57604051635274afe760e01b81526001600160a01b0384166004820152602401610d6a565b5f5f838381518110611dd557611dd5613254565b016020015160f81c90506080811015611df257600191505061104c565b60e08160ff16108015611e0f57508351611e0d846001613091565b105b8015611e4a575083611e22846001613091565b81518110611e3257611e32613254565b602001015160f81c60f81b60f81c60c01660ff166080145b15611e5957600291505061104c565b60f08160ff16108015611e7657508351611e74846002613091565b105b8015611eb1575083611e89846001613091565b81518110611e9957611e99613254565b602001015160f81c60f81b60f81c60c01660ff166080145b8015611eec575083611ec4846002613091565b81518110611ed457611ed4613254565b602001015160f81c60f81b60f81c60c01660ff166080145b15611efb57600391505061104c565b60f88160ff16108015611f1857508351611f16846003613091565b105b8015611f53575083611f2b846001613091565b81518110611f3b57611f3b613254565b602001015160f81c60f81b60f81c60c01660ff166080145b8015611f8e575083611f66846002613091565b81518110611f7657611f76613254565b602001015160f81c60f81b60f81c60c01660ff166080145b8015611fc9575083611fa1846003613091565b81518110611fb157611fb1613254565b602001015160f81c60f81b60f81c60c01660ff166080145b15611fd857600491505061104c565b6040516361709aff60e11b815260040160405180910390fd5b5f5f83838151811061200557612005613254565b016020015160f81c905060cc81148061202157508060ff1660cd145b1561203057600191505061104c565b8060ff1660e214801561204d5750835161204b846002613091565b105b156120d7575f8461205f856001613091565b8151811061206f5761206f613254565b016020015160f81c90505f85612086866002613091565b8151811061209657612096613254565b016020015160f81c9050608060ff83161480156120c357508060ff16608f14806120c357508060ff16608e145b156120d4576001935050505061104c565b50505b8060ff1660f01480156120f4575083516120f2846003613091565b105b156121e4575f84612106856001613091565b8151811061211657612116613254565b016020015160f81c90505f8561212d866002613091565b8151811061213d5761213d613254565b016020015160f81c90505f86612154876003613091565b8151811061216457612164613254565b016020015160f81c9050609f60ff841614801561218457508160ff16608f145b80156121a3575060bb8160ff16101580156121a3575060bf8160ff1611155b806121ce57508260ff16609f1480156121bf57508160ff1660a4145b80156121ce57508060ff1660b0145b156121e057600194505050505061104c565b5050505b8060ff1660ef148015612201575083516121ff846002613091565b105b1561227e575f84612213856001613091565b8151811061222357612223613254565b016020015160f81c90505f8561223a866002613091565b8151811061224a5761224a613254565b016020015160f81c905060b860ff831614801561226a57508060ff16608f145b1561227b576001935050505061104c565b50505b8060ff1660e214801561229b57508351612299846002613091565b105b15612318575f846122ad856001613091565b815181106122bd576122bd613254565b016020015160f81c90505f856122d4866002613091565b815181106122e4576122e4613254565b016020015160f81c9050608360ff831614801561230457508060ff1660a3145b15612315576001935050505061104c565b50505b8060ff1660f314801561233557508351612333846002613091565b105b801561236f575083612348846001613091565b8151811061235857612358613254565b6020910101516001600160f81b031916600560fd1b145b80156123a95750600160ff1b84612387856002613091565b8151811061239757612397613254565b01602001516001600160f81b03191610155b80156123e35750609f60f81b846123c1856002613091565b815181106123d1576123d1613254565b01602001516001600160f81b03191611155b156123f257600191505061104c565b505f9392505050565b5f82828151811061240e5761240e613254565b6020910101516001600160f81b031916607160f91b14801561243a57508251612438836002613091565b105b801561247457508261244d836001613091565b8151811061245d5761245d613254565b6020910101516001600160f81b031916600160ff1b145b8015610c1c575082612487836002613091565b8151811061249757612497613254565b6020910101516001600160f81b031916608d60f81b149392505050565b5f8282815181106124c7576124c7613254565b6020910101516001600160f81b031916600f60fc1b1480156124f3575082516124f1836003613091565b105b801561252d575082612506836001613091565b8151811061251657612516613254565b6020910101516001600160f81b031916609f60f81b145b8015610c1c575082612540836002613091565b8151811061255057612550613254565b6020910101516001600160f81b031916608760f81b149392505050565b60026001540361259057604051633ee5aeb560e01b815260040160405180910390fd5b6002600155565b5f81805190602001206040516020016125dc91907f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c810191909152603c0190565b604051602081830303815290604052805190602001209050919050565b5f6109938484848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506127ae92505050565b604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091528183018690528251808303840181526060830193849052805191012063e32954eb60e01b90925285906001600160a01b0382169063e32954eb906126b390859088908890606401613268565b5f604051808303815f875af11580156126ce573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526126f5919081019061328a565b50505050505050565b6003546040516001600160a01b0390911690637a806d6b9033908490869061272d9089906005906020016133a7565b6040516020818303038152906040526040518563ffffffff1660e01b815260040161275b949392919061344d565b6020604051808303815f875af1158015612777573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061279b9190612edb565b50505050565b6060610c1c83835f6127cc565b5f5f5f5f6127bc8686612865565b92509250925061140782826128ae565b6060814710156127f15760405163cd78605960e01b8152306004820152602401610d6a565b5f5f856001600160a01b0316848660405161280c9190613480565b5f6040518083038185875af1925050503d805f8114612846576040519150601f19603f3d011682016040523d82523d5f602084013e61284b565b606091505b509150915061285b868383612966565b9695505050505050565b5f5f5f835160410361289c576020840151604085015160608601515f1a61288e888285856129c2565b9550955095505050506128a7565b505081515f91506002905b9250925092565b5f8260038111156128c1576128c161348b565b036128ca575050565b60018260038111156128de576128de61348b565b036128fc5760405163f645eedf60e01b815260040160405180910390fd5b60028260038111156129105761291061348b565b036129315760405163fce698f760e01b815260048101829052602401610d6a565b60038260038111156129455761294561348b565b03610fb5576040516335e2f38360e21b815260048101829052602401610d6a565b60608261297b5761297682612a8a565b610c1c565b815115801561299257506001600160a01b0384163b155b156129bb57604051639996b31560e01b81526001600160a01b0385166004820152602401610d6a565b5080610c1c565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411156129fb57505f91506003905082612a80565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015612a4c573d5f5f3e3d5ffd5b5050604051601f1901519150506001600160a01b038116612a7757505f925060019150829050612a80565b92505f91508190505b9450945094915050565b805115612a9a5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b6001600160a01b038116811461102a575f5ffd5b5f60208284031215612ad7575f5ffd5b8135610c1c81612ab3565b5f5f60408385031215612af3575f5ffd5b8235612afe81612ab3565b946020939093013593505050565b5f60208284031215612b1c575f5ffd5b5035919050565b5f5f5f60608486031215612b35575f5ffd5b8335612b4081612ab3565b92506020840135612b5081612ab3565b929592945050506040919091013590565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b0381118282101715612b9d57612b9d612b61565b604052919050565b5f6001600160401b03821115612bbd57612bbd612b61565b50601f01601f191660200190565b5f82601f830112612bda575f5ffd5b8135612bed612be882612ba5565b612b75565b818152846020838601011115612c01575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f5f60408385031215612c2e575f5ffd5b82356001600160401b03811115612c43575f5ffd5b612c4f85828601612bcb565b95602094909401359450505050565b5f60208284031215612c6e575f5ffd5b81356001600160401b03811115612c83575f5ffd5b61099384828501612bcb565b5f5f83601f840112612c9f575f5ffd5b5081356001600160401b03811115612cb5575f5ffd5b602083019150836020828501011115612ccc575f5ffd5b9250929050565b5f5f5f60408486031215612ce5575f5ffd5b83356001600160401b03811115612cfa575f5ffd5b612d0686828701612c8f565b909790965060209590950135949350505050565b5f5f5f60408486031215612d2c575f5ffd5b83356001600160401b03811115612d41575f5ffd5b840160608187031215612d52575f5ffd5b925060208401356001600160401b03811115612d6c575f5ffd5b612d7886828701612c8f565b9497909650939450505050565b5f60e08284031215612d95575f5ffd5b50919050565b5f5f5f60408486031215612dad575f5ffd5b83356001600160401b03811115612dc2575f5ffd5b612dce86828701612d85565b93505060208401356001600160401b03811115612d6c575f5ffd5b5f60208284031215612df9575f5ffd5b81356001600160401b03811115612e0e575f5ffd5b61099384828501612d85565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f610c1c6020830184612e1a565b606081525f612e6c6060830186612e1a565b60208301949094525060400152919050565b5f6040828403128015612e8f575f5ffd5b50604080519081016001600160401b0381118282101715612eb257612eb2612b61565b604052825181526020928301519281019290925250919050565b818382375f9101908152919050565b5f60208284031215612eeb575f5ffd5b5051919050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b604081525f612f2d604083018587612ef2565b9050826020830152949350505050565b801515811461102a575f5ffd5b5f60208284031215612f5a575f5ffd5b8151610c1c81612f3d565b5f823560de19833603018112612f79575f5ffd5b9190910192915050565b5f5f8335601e19843603018112612f98575f5ffd5b8301803591506001600160401b03821115612fb1575f5ffd5b6020019150600581901b3603821315612ccc575f5ffd5b5f5f8335601e19843603018112612fdd575f5ffd5b8301803591506001600160401b03821115612ff6575f5ffd5b602001915036819003821315612ccc575f5ffd5b602081525f610993602083018486612ef2565b5f6020828403121561302d575f5ffd5b8135610c1c81612f3d565b634e487b7160e01b5f52601160045260245ffd5b8181038181111561104c5761104c613038565b600181811c9082168061307357607f821691505b602082108103612d9557634e487b7160e01b5f52602260045260245ffd5b8082018082111561104c5761104c613038565b5f600182016130b5576130b5613038565b5060010190565b5f8383855260208501945060208460051b820101835f5b8681101561314457838303601f19018852813536879003601e190181126130f8575f5ffd5b86016020810190356001600160401b03811115613113575f5ffd5b803603821315613121575f5ffd5b61312c858284612ef2565b60209a8b019a909550939093019250506001016130d3565b50909695505050505050565b61012081525f61316561012083018d8f612ef2565b6001600160a01b038c81166020850152604084018c90528a166060840152828103608084015261319681898b6130bc565b96151560a084015250506001600160a01b039390931660c084015260e083019190915261010090910152979650505050505050565b60e081525f6131de60e083018b8d612ef2565b6001600160a01b038a81166020850152604084018a905288166060840152828103608084015261320f8187896130bc565b94151560a084015250506001600160a01b039190911660c090910152979650505050505050565b5f60ff821660ff810361324b5761324b613038565b60010192915050565b634e487b7160e01b5f52603260045260245ffd5b838152604060208201525f6132816040830184866130bc565b95945050505050565b5f6020828403121561329a575f5ffd5b81516001600160401b038111156132af575f5ffd5b8201601f810184136132bf575f5ffd5b80516001600160401b038111156132d8576132d8612b61565b8060051b6132e860208201612b75565b91825260208184018101929081019087841115613303575f5ffd5b6020850192505b838310156133855782516001600160401b03811115613327575f5ffd5b8501603f81018913613337575f5ffd5b6020810151613348612be882612ba5565b8181526040838301018b101561335c575f5ffd5b8160408401602083015e5f6020838301015280855250505060208201915060208301925061330a565b979650505050505050565b5f81518060208401855e5f93019283525090919050565b5f6133b28285613390565b83545f90600181811c908216806133ca57607f821691505b6020821081036133e857634e487b7160e01b5f52602260045260245ffd5b8080156133fc57600181146134115761343f565b60ff198416865282151583028601945061343f565b5f898152602090205f5b848110156134375781548882015260019091019060200161341b565b505082860194505b509298975050505050505050565b6001600160a01b0385811682528481166020830152831660408201526080606082018190525f9061285b90830184612e1a565b5f610c1c8284613390565b634e487b7160e01b5f52602160045260245ffdfea2646970667358221220da0ca7e1edbb9f75fec4d6f45675905d8a439e3bd51fd05cdba95dfb408b15c764736f6c634300081c00330000000000000000000000005ede4408e78c36c3ab16c5813c418624c2823b27000000000000000000000000bd5cf602e5c62ac1a3a597347952d6ce8b1114b00000000000000000000000003c05f49af5fa3b13ba780e3f1924d1c112bde922000000000000000000000000f55b0b6967db9a0982a62ebcb5226ffbddb80a6f000000000000000000000000a14f63e834dd6b7944bcf68f76a508b617c19c39000000000000000000000000d343a4f2204c1182bb2ee2cd95b677ff811e38c000000000000000000000000043aedb439f497b1d51d1b263d64abf026b2aed5ccac7291742cc038df280cfdc67517aa5d83fe6f4716c336481273a83a877997b0000000000000000000000000000000000000000000000000000000000000140000000000000000000000000dd860bb53d040ad9fbd868c345d18f820a3cd9bc00000000000000000000000000000000000000000000000000000000000000052e62657261000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x608060405260043610610212575f3560e01c80638da5cb5b1161011e578063d3419bf3116100a8578063eeb144da1161006d578063eeb144da1461063d578063f20387df14610650578063f2fde38b14610671578063f978fd6114610690578063faff50a8146106be575f5ffd5b8063d3419bf3146105ad578063d57a11f1146105cc578063dc7daea3146105eb578063e086e5ec1461060a578063e72c1e551461061e575f5ffd5b8063aeb8ce9b116100ee578063aeb8ce9b1461051e578063b36c3be81461053d578063bf80668414610550578063cb37f3b21461056f578063d2ff3bdc1461058e575f5ffd5b80638da5cb5b146104b15780639791c097146104cd5780639ff46e74146104ec578063acf1a8411461050b575f5ffd5b80635d3590d51161019f578063790ca4131161016f578063790ca4131461040f5780637c127a9614610424578063808698531461044157806383e7f6ff146104605780638a95b09f1461049a575f5ffd5b80635d3590d51461037d5780635f17e2651461039c57806365ebf99a146103dc578063715018a6146103fb575f5ffd5b806350cfeddd116101e557806350cfeddd146102ce578063530e784f146102e257806354826fe714610301578063557499ba1461033f5780635829831d1461035e575f5ffd5b8063010adc4d146102165780630495a8441461024c57806313d56a9c14610269578063501b3fd71461028a575b5f5ffd5b348015610221575f5ffd5b50600d546001600160a01b03165b6040516001600160a01b0390911681526020015b60405180910390f35b348015610257575f5ffd5b50600b546001600160a01b031661022f565b348015610274575f5ffd5b50610288610283366004612ac7565b6106f1565b005b348015610295575f5ffd5b506102c06102a4366004612ae2565b600960209081525f928352604080842090915290825290205481565b604051908152602001610243565b3480156102d9575f5ffd5b506102c0600181565b3480156102ed575f5ffd5b506102886102fc366004612ac7565b61074e565b34801561030c575f5ffd5b5061032f61031b366004612b0c565b60086020525f908152604090205460ff1681565b6040519015158152602001610243565b34801561034a575f5ffd5b50610288610359366004612ac7565b6107a4565b348015610369575f5ffd5b50610288610378366004612ac7565b6107fa565b348015610388575f5ffd5b50610288610397366004612b23565b610850565b3480156103a7575f5ffd5b506103ca6103b6366004612ac7565b600e6020525f908152604090205460ff1681565b60405160ff9091168152602001610243565b3480156103e7575f5ffd5b506102886103f6366004612ac7565b610871565b348015610406575f5ffd5b506102886108ee565b34801561041a575f5ffd5b506102c0600a5481565b34801561042f575f5ffd5b50600c546001600160a01b031661022f565b34801561044c575f5ffd5b5060035461022f906001600160a01b031681565b34801561046b575f5ffd5b5061047f61047a366004612c1d565b610901565b60408051825181526020928301519281019290925201610243565b3480156104a5575f5ffd5b506102c06301e1338081565b3480156104bc575f5ffd5b505f546001600160a01b031661022f565b3480156104d8575f5ffd5b5061032f6104e7366004612c5e565b61099b565b3480156104f7575f5ffd5b50610288610506366004612b0c565b6109d6565b610288610519366004612cd3565b610a34565b348015610529575f5ffd5b5061032f610538366004612c5e565b610b7c565b61028861054b366004612d1a565b610c23565b34801561055b575f5ffd5b5061028861056a366004612ac7565b610c52565b34801561057a575f5ffd5b5060065461022f906001600160a01b031681565b348015610599575f5ffd5b5060045461022f906001600160a01b031681565b3480156105b8575f5ffd5b5060025461022f906001600160a01b031681565b3480156105d7575f5ffd5b506102886105e6366004612d9b565b610ca8565b3480156105f6575f5ffd5b50610288610605366004612de9565b610e22565b348015610615575f5ffd5b50610288610fb9565b348015610629575f5ffd5b506102c0610638366004612c1d565b61102d565b61028861064b366004612de9565b611052565b34801561065b575f5ffd5b50610664611087565b6040516102439190612e48565b34801561067c575f5ffd5b5061028861068b366004612ac7565b611113565b34801561069b575f5ffd5b5061032f6106aa366004612b0c565b60076020525f908152604090205460ff1681565b3480156106c9575f5ffd5b506102c07fcac7291742cc038df280cfdc67517aa5d83fe6f4716c336481273a83a877997b81565b6106f961114d565b600c80546001600160a01b0319166001600160a01b0383169081179091556040519081527f63651f54b104da052b16eb4d518afa4c0b1f6d2b77b9ab0f445787585234de37906020015b60405180910390a150565b61075661114d565b600280546001600160a01b0319166001600160a01b0383169081179091556040519081527fefe8ab924ca486283a79dc604baa67add51afb82af1db8ac386ebbba643cdffd90602001610743565b6107ac61114d565b600380546001600160a01b0319166001600160a01b0383169081179091556040519081527fd192c0b229b00473ccb6ccfebf6642805bca1dcdf2d9fb4fd102c7dc7ea4ce2390602001610743565b61080261114d565b600b80546001600160a01b0319166001600160a01b0383169081179091556040519081527f1c8833ad9579b88233573f0b91eb8ab86e24450f9e11151c6387dff4d5b4f61a90602001610743565b61085861114d565b61086c6001600160a01b0384168383611179565b505050565b61087961114d565b6001600160a01b0381166108a0576040516301ed76a760e61b815260040160405180910390fd5b600680546001600160a01b0319166001600160a01b0383169081179091556040519081527f6cfddd24d2afc1b9f31d51f0ef77029fdde044799f0a87a2a09b7673b609742290602001610743565b6108f661114d565b6108ff5f6111cb565b565b604080518082019091525f8082526020820152825160208401206002546001600160a01b03166350e9a715856109368461121a565b866040518463ffffffff1660e01b815260040161095593929190612e5a565b6040805180830381865afa15801561096f573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109939190612e7e565b949350505050565b5f5f6109a5835190565b90505f6109b1846112c1565b90505f8211801561099357506001811480156109cd5750600182115b15949350505050565b6109de61114d565b428110156109ff5760405163f7235ed760e01b815260040160405180910390fd5b600a8190556040518181527fdb5fc205901030b15dae0c28aeedbdf381585f7e12f86855899a3b5328aa34e990602001610743565b5f8383604051610a45929190612ecc565b604080519182900382206020601f8701819004810284018101909252858352925082915f91610a90919088908890819084018382808284375f9201919091525088925061102d915050565b9050610a9b81611411565b60405163c475abff60e01b815260048101839052602481018590525f907f0000000000000000000000005ede4408e78c36c3ab16c5813c418624c2823b276001600160a01b03169063c475abff906044016020604051808303815f875af1158015610b08573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b2c9190612edb565b9050610b378261146a565b837f93bc1a84707231b1d9552157299797c64a1a8c5bc79f05153716630c9c4936fc888884604051610b6b93929190612f1a565b60405180910390a250505050505050565b805160208201205f90610b8e8361099b565b8015610c1c5750604051633a178d9960e01b8152600481018290527f0000000000000000000000005ede4408e78c36c3ab16c5813c418624c2823b276001600160a01b031690633a178d9990602401602060405180830381865afa158015610bf8573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c1c9190612f4a565b9392505050565b610c2e8383836114f1565b610c40610c3b8480612f65565b6116e3565b61086c610c4d8480612f65565b6117c9565b610c5a61114d565b600d80546001600160a01b0319166001600160a01b0383169081179091556040519081527f3639a5ccd808ae1a86d60a5b738cd981061b7478ad45ae0b2aea54994938022b90602001610743565b825f610cb76080830183612f83565b9050118015610cdd57505f610cd26080830160608401612ac7565b6001600160a01b0316145b15610cfb576040516334fd817160e21b815260040160405180910390fd5b610d41610d088280612fc8565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610b7c92505050565b610d7357610d4f8180612fc8565b6040516308eee0fd60e31b8152600401610d6a92919061300a565b60405180910390fd5b6301e1338081604001351015610da25760408051639a71997b60e01b8152908201356004820152602401610d6a565b610dad8484846118ce565b5f610df4610dbb8680612fc8565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506112c192505050565b90506003811015610e0957610d4f8580612fc8565b610e12856116e3565b610e1b85611a65565b5050505050565b805f610e316080830183612f83565b9050118015610e5757505f610e4c6080830160608401612ac7565b6001600160a01b0316145b15610e75576040516334fd817160e21b815260040160405180910390fd5b610e82610d088280612fc8565b610e9057610d4f8180612fc8565b6301e1338081604001351015610ebf5760408051639a71997b60e01b8152908201356004820152602401610d6a565b600b546001600160a01b03163314610eea5760405163e0d1f21760e01b815260040160405180910390fd5b6004546001600160a01b0316631c40a2ac610f058480612fc8565b6040518363ffffffff1660e01b8152600401610f2292919061300a565b602060405180830381865afa158015610f3d573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f619190612f4a565b610f7e57604051637d6fe8d760e11b815260040160405180910390fd5b610f8e60c0830160a0840161301d565b15610fac5760405163b1a5a8ef60e01b815260040160405180910390fd5b610fb582611a65565b5050565b6006546040515f916001600160a01b03169047908381818185875af1925050503d805f8114611003576040519150601f19603f3d011682016040523d82523d5f602084013e611008565b606091505b505090508061102a576040516312171d8360e31b815260040160405180910390fd5b50565b5f5f6110398484610901565b602081015181519192506109939161304c565b92915050565b600a544210156110755760405163a9f4f87160e01b815260040160405180910390fd5b61107e816116e3565b61102a816117c9565b600580546110949061305f565b80601f01602080910402602001604051908101604052809291908181526020018280546110c09061305f565b801561110b5780601f106110e25761010080835404028352916020019161110b565b820191905f5260205f20905b8154815290600101906020018083116110ee57829003601f168201915b505050505081565b61111b61114d565b6001600160a01b03811661114457604051631e4fbdf760e01b81525f6004820152602401610d6a565b61102a816111cb565b5f546001600160a01b031633146108ff5760405163118cdaa760e01b8152336004820152602401610d6a565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261086c908490611d60565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60405163727e4ea760e01b8152600481018290525f907f0000000000000000000000005ede4408e78c36c3ab16c5813c418624c2823b276001600160a01b03169063727e4ea790602401602060405180830381865afa15801561127f573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112a39190612edb565b9050805f036112b4575050600a5490565b61104c62278d0082613091565b80515f908290829081905b80821015611407575f6112df8584611dc1565b90505f6112ec8285613091565b90505b828110801561130357506113038682611ff1565b15611323576113128682611dc1565b61131c9082613091565b90506112ef565b8281108015611337575061133786826123fb565b156113ae576113468682611dc1565b6113509082613091565b9050828110156113ae575f6113658783611dc1565b90506113718183613091565b91505b838210801561138857506113888783611ff1565b156113a8576113978783611dc1565b6113a19083613091565b9150611374565b50611323565b6113b886856124b4565b80156113c357508281105b80156113d457506113d486826124b4565b156113f0576113e38682611dc1565b6113ed9082613091565b90505b846113fa816130a4565b95505080935050506112cc565b5090949350505050565b803410156114325760405163044044a560e21b815260040160405180910390fd5b60405181815233907fbc769889246686134856b409155bb87630ea5797a705fa98b61f576d316aab9b9060200160405180910390a250565b61147261256d565b803411156114e8575f33611486833461304c565b6040515f81818185875af1925050503d805f81146114bf576040519150601f19603f3d011682016040523d82523d5f602084013e6114c4565b606091505b50509050806114e6576040516312171d8360e31b815260040160405180910390fd5b505b61102a60018055565b5f6114fc8480612f65565b6115069080612fc8565b6115108680612f65565b611521906040810190602001612ac7565b61152b8780612f65565b604001356115398880612f65565b61154a906080810190606001612ac7565b6115548980612f65565b611562906080810190612f83565b61156c8b80612f65565b61157d9060c081019060a00161301d565b6115878c80612f65565b6115989060e081019060c001612ac7565b8c602001358d604001356040516020016115bc9b9a99989796959493929190613150565b60405160208183030381529060405290505f6115d782612597565b5f8181526007602052604090205490915060ff16156116095760405163900bb2c960e01b815260040160405180910390fd5b335f9081526009602090815260408083208289013584529091529081902054908601351161164a5760405163771a50b360e01b815260040160405180910390fd5b5f6116568286866125f9565b90506001600160a01b038116158061167c5750600c546001600160a01b03828116911614155b1561169a57604051638baa579f60e01b815260040160405180910390fd5b5f828152600760209081526040808320805460ff191660011790553383526009825280832089830135845290915281208054916116d6836130a4565b9190505550505050505050565b6004546001600160a01b0316631c40a2ac6116fe8380612fc8565b6040518363ffffffff1660e01b815260040161171b92919061300a565b602060405180830381865afa158015611736573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061175a9190612f4a565b1561177857604051632bbd1e6760e11b815260040160405180910390fd5b336117896040830160208401612ac7565b6001600160a01b0316141580156117ab57506117ab60c0820160a0830161301d565b1561102a57604051636eb6599d60e01b815260040160405180910390fd5b805f6117d86080830183612f83565b90501180156117fe57505f6117f36080830160608401612ac7565b6001600160a01b0316145b1561181c576040516334fd817160e21b815260040160405180910390fd5b611829610d088280612fc8565b61183757610d4f8180612fc8565b6301e13380816040013510156118665760408051639a71997b60e01b8152908201356004820152602401610d6a565b5f6118b16118748480612fc8565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250505050604085013561102d565b90506118bc81611411565b6118c583611a65565b61086c8161146a565b5f6118d98480612fc8565b6118e96040870160208801612ac7565b60408701356118fe6080890160608a01612ac7565b61190b60808a018a612f83565b61191b60c08c0160a08d0161301d565b61192b60e08d0160c08e01612ac7565b604051602001611943999897969594939291906131cb565b60405160208183030381529060405290505f61195e82612597565b5f8181526008602052604090205490915060ff161561199057604051633d47d82360e01b815260040160405180910390fd5b335f908152600e602052604090205460ff16156119c05760405163113d0d3f60e11b815260040160405180910390fd5b5f6119cc8286866125f9565b90506001600160a01b03811615806119f25750600d546001600160a01b03828116911614155b15611a1057604051638baa579f60e01b815260040160405180910390fd5b5f828152600860209081526040808320805460ff19166001179055338352600e9091528120805460ff1691611a4483613236565b91906101000a81548160ff021916908360ff16021790555050505050505050565b5f6001600160a01b037f0000000000000000000000005ede4408e78c36c3ab16c5813c418624c2823b271663eac2aa09611a9f8480612fc8565b604051611aad929190612ecc565b604080519182900390912090611ac890860160208701612ac7565b6040860135611add6080880160608901612ac7565b6040516001600160e01b031960e087901b16815260048101949094526001600160a01b03928316602485015260448401919091521660648201525f608482015260a4016020604051808303815f875af1158015611b3c573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b609190612edb565b90505f611b706080840184612f83565b90501115611bbe57611bbe611b8b6080840160608501612ac7565b611b958480612fc8565b604051611ba3929190612ecc565b604051908190039020611bb96080860186612f83565b612639565b611bce60c0830160a0840161301d565b15611c2a57611c2a611be08380612fc8565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611c24925050506080850160608601612ac7565b336126fe565b611c3a6040830160208401612ac7565b6001600160a01b0316611c4d8380612fc8565b604051611c5b929190612ecc565b6040519081900390207f0667086d08417333ce63f40d5bc2ef6fd330e25aaaf317b7c489541f8fe600fa611c8f8580612fc8565b85604051611c9f93929190612f1a565b60405180910390a35f611cb860e0840160c08501612ac7565b6001600160a01b031614610fb557611cd660e0830160c08401612ac7565b6001600160a01b0316611cef6040840160208501612ac7565b6001600160a01b0316611d028480612fc8565b604051611d10929190612ecc565b6040519081900390207f1124fcbf46055234a873086b844a44635d54b982d7b4ca7e1631d51a7950e665611d448680612fc8565b86604051611d5493929190612f1a565b60405180910390a45050565b5f611d746001600160a01b038416836127a1565b905080515f14158015611d98575080806020019051810190611d969190612f4a565b155b1561086c57604051635274afe760e01b81526001600160a01b0384166004820152602401610d6a565b5f5f838381518110611dd557611dd5613254565b016020015160f81c90506080811015611df257600191505061104c565b60e08160ff16108015611e0f57508351611e0d846001613091565b105b8015611e4a575083611e22846001613091565b81518110611e3257611e32613254565b602001015160f81c60f81b60f81c60c01660ff166080145b15611e5957600291505061104c565b60f08160ff16108015611e7657508351611e74846002613091565b105b8015611eb1575083611e89846001613091565b81518110611e9957611e99613254565b602001015160f81c60f81b60f81c60c01660ff166080145b8015611eec575083611ec4846002613091565b81518110611ed457611ed4613254565b602001015160f81c60f81b60f81c60c01660ff166080145b15611efb57600391505061104c565b60f88160ff16108015611f1857508351611f16846003613091565b105b8015611f53575083611f2b846001613091565b81518110611f3b57611f3b613254565b602001015160f81c60f81b60f81c60c01660ff166080145b8015611f8e575083611f66846002613091565b81518110611f7657611f76613254565b602001015160f81c60f81b60f81c60c01660ff166080145b8015611fc9575083611fa1846003613091565b81518110611fb157611fb1613254565b602001015160f81c60f81b60f81c60c01660ff166080145b15611fd857600491505061104c565b6040516361709aff60e11b815260040160405180910390fd5b5f5f83838151811061200557612005613254565b016020015160f81c905060cc81148061202157508060ff1660cd145b1561203057600191505061104c565b8060ff1660e214801561204d5750835161204b846002613091565b105b156120d7575f8461205f856001613091565b8151811061206f5761206f613254565b016020015160f81c90505f85612086866002613091565b8151811061209657612096613254565b016020015160f81c9050608060ff83161480156120c357508060ff16608f14806120c357508060ff16608e145b156120d4576001935050505061104c565b50505b8060ff1660f01480156120f4575083516120f2846003613091565b105b156121e4575f84612106856001613091565b8151811061211657612116613254565b016020015160f81c90505f8561212d866002613091565b8151811061213d5761213d613254565b016020015160f81c90505f86612154876003613091565b8151811061216457612164613254565b016020015160f81c9050609f60ff841614801561218457508160ff16608f145b80156121a3575060bb8160ff16101580156121a3575060bf8160ff1611155b806121ce57508260ff16609f1480156121bf57508160ff1660a4145b80156121ce57508060ff1660b0145b156121e057600194505050505061104c565b5050505b8060ff1660ef148015612201575083516121ff846002613091565b105b1561227e575f84612213856001613091565b8151811061222357612223613254565b016020015160f81c90505f8561223a866002613091565b8151811061224a5761224a613254565b016020015160f81c905060b860ff831614801561226a57508060ff16608f145b1561227b576001935050505061104c565b50505b8060ff1660e214801561229b57508351612299846002613091565b105b15612318575f846122ad856001613091565b815181106122bd576122bd613254565b016020015160f81c90505f856122d4866002613091565b815181106122e4576122e4613254565b016020015160f81c9050608360ff831614801561230457508060ff1660a3145b15612315576001935050505061104c565b50505b8060ff1660f314801561233557508351612333846002613091565b105b801561236f575083612348846001613091565b8151811061235857612358613254565b6020910101516001600160f81b031916600560fd1b145b80156123a95750600160ff1b84612387856002613091565b8151811061239757612397613254565b01602001516001600160f81b03191610155b80156123e35750609f60f81b846123c1856002613091565b815181106123d1576123d1613254565b01602001516001600160f81b03191611155b156123f257600191505061104c565b505f9392505050565b5f82828151811061240e5761240e613254565b6020910101516001600160f81b031916607160f91b14801561243a57508251612438836002613091565b105b801561247457508261244d836001613091565b8151811061245d5761245d613254565b6020910101516001600160f81b031916600160ff1b145b8015610c1c575082612487836002613091565b8151811061249757612497613254565b6020910101516001600160f81b031916608d60f81b149392505050565b5f8282815181106124c7576124c7613254565b6020910101516001600160f81b031916600f60fc1b1480156124f3575082516124f1836003613091565b105b801561252d575082612506836001613091565b8151811061251657612516613254565b6020910101516001600160f81b031916609f60f81b145b8015610c1c575082612540836002613091565b8151811061255057612550613254565b6020910101516001600160f81b031916608760f81b149392505050565b60026001540361259057604051633ee5aeb560e01b815260040160405180910390fd5b6002600155565b5f81805190602001206040516020016125dc91907f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c810191909152603c0190565b604051602081830303815290604052805190602001209050919050565b5f6109938484848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506127ae92505050565b604080517fcac7291742cc038df280cfdc67517aa5d83fe6f4716c336481273a83a877997b6020808301919091528183018690528251808303840181526060830193849052805191012063e32954eb60e01b90925285906001600160a01b0382169063e32954eb906126b390859088908890606401613268565b5f604051808303815f875af11580156126ce573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526126f5919081019061328a565b50505050505050565b6003546040516001600160a01b0390911690637a806d6b9033908490869061272d9089906005906020016133a7565b6040516020818303038152906040526040518563ffffffff1660e01b815260040161275b949392919061344d565b6020604051808303815f875af1158015612777573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061279b9190612edb565b50505050565b6060610c1c83835f6127cc565b5f5f5f5f6127bc8686612865565b92509250925061140782826128ae565b6060814710156127f15760405163cd78605960e01b8152306004820152602401610d6a565b5f5f856001600160a01b0316848660405161280c9190613480565b5f6040518083038185875af1925050503d805f8114612846576040519150601f19603f3d011682016040523d82523d5f602084013e61284b565b606091505b509150915061285b868383612966565b9695505050505050565b5f5f5f835160410361289c576020840151604085015160608601515f1a61288e888285856129c2565b9550955095505050506128a7565b505081515f91506002905b9250925092565b5f8260038111156128c1576128c161348b565b036128ca575050565b60018260038111156128de576128de61348b565b036128fc5760405163f645eedf60e01b815260040160405180910390fd5b60028260038111156129105761291061348b565b036129315760405163fce698f760e01b815260048101829052602401610d6a565b60038260038111156129455761294561348b565b03610fb5576040516335e2f38360e21b815260048101829052602401610d6a565b60608261297b5761297682612a8a565b610c1c565b815115801561299257506001600160a01b0384163b155b156129bb57604051639996b31560e01b81526001600160a01b0385166004820152602401610d6a565b5080610c1c565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411156129fb57505f91506003905082612a80565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015612a4c573d5f5f3e3d5ffd5b5050604051601f1901519150506001600160a01b038116612a7757505f925060019150829050612a80565b92505f91508190505b9450945094915050565b805115612a9a5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b6001600160a01b038116811461102a575f5ffd5b5f60208284031215612ad7575f5ffd5b8135610c1c81612ab3565b5f5f60408385031215612af3575f5ffd5b8235612afe81612ab3565b946020939093013593505050565b5f60208284031215612b1c575f5ffd5b5035919050565b5f5f5f60608486031215612b35575f5ffd5b8335612b4081612ab3565b92506020840135612b5081612ab3565b929592945050506040919091013590565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b0381118282101715612b9d57612b9d612b61565b604052919050565b5f6001600160401b03821115612bbd57612bbd612b61565b50601f01601f191660200190565b5f82601f830112612bda575f5ffd5b8135612bed612be882612ba5565b612b75565b818152846020838601011115612c01575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f5f60408385031215612c2e575f5ffd5b82356001600160401b03811115612c43575f5ffd5b612c4f85828601612bcb565b95602094909401359450505050565b5f60208284031215612c6e575f5ffd5b81356001600160401b03811115612c83575f5ffd5b61099384828501612bcb565b5f5f83601f840112612c9f575f5ffd5b5081356001600160401b03811115612cb5575f5ffd5b602083019150836020828501011115612ccc575f5ffd5b9250929050565b5f5f5f60408486031215612ce5575f5ffd5b83356001600160401b03811115612cfa575f5ffd5b612d0686828701612c8f565b909790965060209590950135949350505050565b5f5f5f60408486031215612d2c575f5ffd5b83356001600160401b03811115612d41575f5ffd5b840160608187031215612d52575f5ffd5b925060208401356001600160401b03811115612d6c575f5ffd5b612d7886828701612c8f565b9497909650939450505050565b5f60e08284031215612d95575f5ffd5b50919050565b5f5f5f60408486031215612dad575f5ffd5b83356001600160401b03811115612dc2575f5ffd5b612dce86828701612d85565b93505060208401356001600160401b03811115612d6c575f5ffd5b5f60208284031215612df9575f5ffd5b81356001600160401b03811115612e0e575f5ffd5b61099384828501612d85565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f610c1c6020830184612e1a565b606081525f612e6c6060830186612e1a565b60208301949094525060400152919050565b5f6040828403128015612e8f575f5ffd5b50604080519081016001600160401b0381118282101715612eb257612eb2612b61565b604052825181526020928301519281019290925250919050565b818382375f9101908152919050565b5f60208284031215612eeb575f5ffd5b5051919050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b604081525f612f2d604083018587612ef2565b9050826020830152949350505050565b801515811461102a575f5ffd5b5f60208284031215612f5a575f5ffd5b8151610c1c81612f3d565b5f823560de19833603018112612f79575f5ffd5b9190910192915050565b5f5f8335601e19843603018112612f98575f5ffd5b8301803591506001600160401b03821115612fb1575f5ffd5b6020019150600581901b3603821315612ccc575f5ffd5b5f5f8335601e19843603018112612fdd575f5ffd5b8301803591506001600160401b03821115612ff6575f5ffd5b602001915036819003821315612ccc575f5ffd5b602081525f610993602083018486612ef2565b5f6020828403121561302d575f5ffd5b8135610c1c81612f3d565b634e487b7160e01b5f52601160045260245ffd5b8181038181111561104c5761104c613038565b600181811c9082168061307357607f821691505b602082108103612d9557634e487b7160e01b5f52602260045260245ffd5b8082018082111561104c5761104c613038565b5f600182016130b5576130b5613038565b5060010190565b5f8383855260208501945060208460051b820101835f5b8681101561314457838303601f19018852813536879003601e190181126130f8575f5ffd5b86016020810190356001600160401b03811115613113575f5ffd5b803603821315613121575f5ffd5b61312c858284612ef2565b60209a8b019a909550939093019250506001016130d3565b50909695505050505050565b61012081525f61316561012083018d8f612ef2565b6001600160a01b038c81166020850152604084018c90528a166060840152828103608084015261319681898b6130bc565b96151560a084015250506001600160a01b039390931660c084015260e083019190915261010090910152979650505050505050565b60e081525f6131de60e083018b8d612ef2565b6001600160a01b038a81166020850152604084018a905288166060840152828103608084015261320f8187896130bc565b94151560a084015250506001600160a01b039190911660c090910152979650505050505050565b5f60ff821660ff810361324b5761324b613038565b60010192915050565b634e487b7160e01b5f52603260045260245ffd5b838152604060208201525f6132816040830184866130bc565b95945050505050565b5f6020828403121561329a575f5ffd5b81516001600160401b038111156132af575f5ffd5b8201601f810184136132bf575f5ffd5b80516001600160401b038111156132d8576132d8612b61565b8060051b6132e860208201612b75565b91825260208184018101929081019087841115613303575f5ffd5b6020850192505b838310156133855782516001600160401b03811115613327575f5ffd5b8501603f81018913613337575f5ffd5b6020810151613348612be882612ba5565b8181526040838301018b101561335c575f5ffd5b8160408401602083015e5f6020838301015280855250505060208201915060208301925061330a565b979650505050505050565b5f81518060208401855e5f93019283525090919050565b5f6133b28285613390565b83545f90600181811c908216806133ca57607f821691505b6020821081036133e857634e487b7160e01b5f52602260045260245ffd5b8080156133fc57600181146134115761343f565b60ff198416865282151583028601945061343f565b5f898152602090205f5b848110156134375781548882015260019091019060200161341b565b505082860194505b509298975050505050505050565b6001600160a01b0385811682528481166020830152831660408201526080606082018190525f9061285b90830184612e1a565b5f610c1c8284613390565b634e487b7160e01b5f52602160045260245ffdfea2646970667358221220da0ca7e1edbb9f75fec4d6f45675905d8a439e3bd51fd05cdba95dfb408b15c764736f6c634300081c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000005ede4408e78c36c3ab16c5813c418624c2823b27000000000000000000000000bd5cf602e5c62ac1a3a597347952d6ce8b1114b00000000000000000000000003c05f49af5fa3b13ba780e3f1924d1c112bde922000000000000000000000000f55b0b6967db9a0982a62ebcb5226ffbddb80a6f000000000000000000000000a14f63e834dd6b7944bcf68f76a508b617c19c39000000000000000000000000d343a4f2204c1182bb2ee2cd95b677ff811e38c000000000000000000000000043aedb439f497b1d51d1b263d64abf026b2aed5ccac7291742cc038df280cfdc67517aa5d83fe6f4716c336481273a83a877997b0000000000000000000000000000000000000000000000000000000000000140000000000000000000000000dd860bb53d040ad9fbd868c345d18f820a3cd9bc00000000000000000000000000000000000000000000000000000000000000052e62657261000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : base_ (address): 0x5ede4408e78c36C3AB16C5813c418624C2823b27
Arg [1] : prices_ (address): 0xbD5cf602E5C62ac1A3A597347952D6cE8B1114b0
Arg [2] : reverseRegistrar_ (address): 0x3c05f49Af5fa3b13ba780e3f1924D1c112BdE922
Arg [3] : whitelistSigner_ (address): 0xF55b0b6967Db9a0982A62EBCb5226FFbDDb80A6f
Arg [4] : freeWhitelistSigner_ (address): 0xA14F63e834dd6b7944bCf68F76A508b617C19c39
Arg [5] : reservedRegistry_ (address): 0xd343A4F2204c1182BB2ee2cD95b677FF811e38C0
Arg [6] : owner_ (address): 0x43aedB439F497b1d51D1b263D64Abf026B2Aed5c
Arg [7] : rootNode_ (bytes32): 0xcac7291742cc038df280cfdc67517aa5d83fe6f4716c336481273a83a877997b
Arg [8] : rootName_ (string): .bera
Arg [9] : paymentReceiver_ (address): 0xDd860bB53d040ad9fbd868c345d18F820a3CD9bc
-----Encoded View---------------
12 Constructor Arguments found :
Arg [0] : 0000000000000000000000005ede4408e78c36c3ab16c5813c418624c2823b27
Arg [1] : 000000000000000000000000bd5cf602e5c62ac1a3a597347952d6ce8b1114b0
Arg [2] : 0000000000000000000000003c05f49af5fa3b13ba780e3f1924d1c112bde922
Arg [3] : 000000000000000000000000f55b0b6967db9a0982a62ebcb5226ffbddb80a6f
Arg [4] : 000000000000000000000000a14f63e834dd6b7944bcf68f76a508b617c19c39
Arg [5] : 000000000000000000000000d343a4f2204c1182bb2ee2cd95b677ff811e38c0
Arg [6] : 00000000000000000000000043aedb439f497b1d51d1b263d64abf026b2aed5c
Arg [7] : cac7291742cc038df280cfdc67517aa5d83fe6f4716c336481273a83a877997b
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000140
Arg [9] : 000000000000000000000000dd860bb53d040ad9fbd868c345d18f820a3cd9bc
Arg [10] : 0000000000000000000000000000000000000000000000000000000000000005
Arg [11] : 2e62657261000000000000000000000000000000000000000000000000000000
Deployed Bytecode Sourcemap
1050:30335:19:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;25953:115;;;;;;;;;;-1:-1:-1;26038:23:19;;-1:-1:-1;;;;;26038:23:19;25953:115;;;-1:-1:-1;;;;;178:32:49;;;160:51;;148:2;133:18;25953:115:19;;;;;;;;26179:107;;;;;;;;;;-1:-1:-1;26260:19:19;;-1:-1:-1;;;;;26260:19:19;26179:107;;30947:203;;;;;;;;;;-1:-1:-1;30947:203:19;;;;;:::i;:::-;;:::i;:::-;;9207:81;;;;;;;;;;-1:-1:-1;9207:81:19;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;1128:25:49;;;1116:2;1101:18;9207:81:19;982:177:49;9672:43:19;;;;;;;;;;;;9714:1;9672:43;;13447:149;;;;;;;;;;-1:-1:-1;13447:149:19;;;;;:::i;:::-;;:::i;9009:55::-;;;;;;;;;;-1:-1:-1;9009:55:19;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;1787:14:49;;1780:22;1762:41;;1750:2;1735:18;9009:55:19;1622:187:49;13844:177:19;;;;;;;;;;-1:-1:-1;13844:177:19;;;;;:::i;:::-;;:::i;30739:202::-;;;;;;;;;;-1:-1:-1;30739:202:19;;;;;:::i;:::-;;:::i;30443:145::-;;;;;;;;;;-1:-1:-1;30443:145:19;;;;;:::i;:::-;;:::i;10089:51::-;;;;;;;;;;-1:-1:-1;10089:51:19;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;2777:4:49;2765:17;;;2747:36;;2735:2;2720:18;10089:51:19;2605:184:49;14655:256:19;;;;;;;;;;-1:-1:-1;14655:256:19;;;;;:::i;:::-;;:::i;2293:101:0:-;;;;;;;;;;;;;:::i;9383:25:19:-;;;;;;;;;;;;;;;;25727:107;;;;;;;;;;-1:-1:-1;25808:19:19;;-1:-1:-1;;;;;25808:19:19;25727:107;;8294:41;;;;;;;;;;-1:-1:-1;8294:41:19;;;;-1:-1:-1;;;;;8294:41:19;;;16328:240;;;;;;;;;;-1:-1:-1;16328:240:19;;;;;:::i;:::-;;:::i;:::-;;;;4776:13:49;;4758:32;;4846:4;4834:17;;;4828:24;4806:20;;;4799:54;;;;4731:18;16328:240:19;4566:293:49;9564:60:19;;;;;;;;;;;;9616:8;9564:60;;1638:85:0;;;;;;;;;;-1:-1:-1;1684:7:0;1710:6;-1:-1:-1;;;;;1710:6:0;1638:85;;15326:240:19;;;;;;;;;;-1:-1:-1;15326:240:19;;;;;:::i;:::-;;:::i;14160:244::-;;;;;;;;;;-1:-1:-1;14160:244:19;;;;;:::i;:::-;;:::i;21027:411::-;;;;;;:::i;:::-;;:::i;15811:185::-;;;;;;;;;;-1:-1:-1;15811:185:19;;;;;:::i;:::-;;:::i;18044:266::-;;;;;;:::i;:::-;;:::i;31156:227::-;;;;;;;;;;-1:-1:-1;31156:227:19;;;;;:::i;:::-;;:::i;8812:30::-;;;;;;;;;;-1:-1:-1;8812:30:19;;;;-1:-1:-1;;;;;8812:30:19;;;8412:41;;;;;;;;;;-1:-1:-1;8412:41:19;;;;-1:-1:-1;;;;;8412:41:19;;;8191:26;;;;;;;;;;-1:-1:-1;8191:26:19;;;;-1:-1:-1;;;;;8191:26:19;;;18561:392;;;;;;;;;;-1:-1:-1;18561:392:19;;;;;:::i;:::-;;:::i;19357:422::-;;;;;;;;;;-1:-1:-1;19357:422:19;;;;;:::i;:::-;;:::i;30176:171::-;;;;;;;;;;;;;:::i;16879:211::-;;;;;;;;;;-1:-1:-1;16879:211:19;;;;;:::i;:::-;;:::i;17449:157::-;;;;;;:::i;:::-;;:::i;8695:22::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;2543:215:0:-;;;;;;;;;;-1:-1:-1;2543:215:0;;;;;:::i;:::-;;:::i;8897:46:19:-;;;;;;;;;;-1:-1:-1;8897:46:19;;;;;:::i;:::-;;;;;;;;;;;;;;;;8567:33;;;;;;;;;;;;;;;30947:203;1531:13:0;:11;:13::i;:::-;31038:19:19::1;:42:::0;;-1:-1:-1;;;;;;31038:42:19::1;-1:-1:-1::0;;;;;31038:42:19;::::1;::::0;;::::1;::::0;;;31095:48:::1;::::0;160:51:49;;;31095:48:19::1;::::0;148:2:49;133:18;31095:48:19::1;;;;;;;;30947:203:::0;:::o;13447:149::-;1531:13:0;:11;:13::i;:::-;13522:6:19::1;:16:::0;;-1:-1:-1;;;;;;13522:16:19::1;-1:-1:-1::0;;;;;13522:16:19;::::1;::::0;;::::1;::::0;;;13553:36:::1;::::0;160:51:49;;;13553:36:19::1;::::0;148:2:49;133:18;13553:36:19::1;14:203:49::0;13844:177:19;1531:13:0;:11;:13::i;:::-;13930:16:19::1;:27:::0;;-1:-1:-1;;;;;;13930:27:19::1;-1:-1:-1::0;;;;;13930:27:19;::::1;::::0;;::::1;::::0;;;13972:42:::1;::::0;160:51:49;;;13972:42:19::1;::::0;148:2:49;133:18;13972:42:19::1;14:203:49::0;30739:202:19;1531:13:0;:11;:13::i;:::-;30830:19:19::1;:42:::0;;-1:-1:-1;;;;;;30830:42:19::1;-1:-1:-1::0;;;;;30830:42:19;::::1;::::0;;::::1;::::0;;;30887:47:::1;::::0;160:51:49;;;30887:47:19::1;::::0;148:2:49;133:18;30887:47:19::1;14:203:49::0;30443:145:19;1531:13:0;:11;:13::i;:::-;30540:41:19::1;-1:-1:-1::0;;;;;30540:27:19;::::1;30568:3:::0;30573:7;30540:27:::1;:41::i;:::-;30443:145:::0;;;:::o;14655:256::-;1531:13:0;:11;:13::i;:::-;-1:-1:-1;;;;;14742:30:19;::::1;14738:67;;14781:24;;-1:-1:-1::0;;;14781:24:19::1;;;;;;;;;;;14738:67;14815:15;:34:::0;;-1:-1:-1;;;;;;14815:34:19::1;-1:-1:-1::0;;;;;14815:34:19;::::1;::::0;;::::1;::::0;;;14864:40:::1;::::0;160:51:49;;;14864:40:19::1;::::0;148:2:49;133:18;14864:40:19::1;14:203:49::0;2293:101:0;1531:13;:11;:13::i;:::-;2357:30:::1;2384:1;2357:18;:30::i;:::-;2293:101::o:0;16328:240:19:-;-1:-1:-1;;;;;;;;;;;;;;;;;16465:22:19;;;;;;16505:6;;-1:-1:-1;;;;;16505:6:19;:12;16481:4;16524:26;16465:22;16524:10;:26::i;:::-;16552:8;16505:56;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;16497:64;16328:240;-1:-1:-1;;;;16328:240:19:o;15326:::-;15382:4;15398:14;15415:17;:4;199:15:48;;113:108;15415:17:19;15398:34;;15442:14;15459:13;:4;:11;:13::i;:::-;15442:30;;15498:1;15489:6;:10;:70;;;;;9714:1;15505:6;:25;:53;;;;;9714:1;15534:6;:24;15505:53;15503:56;15482:77;15326:240;-1:-1:-1;;;;15326:240:19:o;14160:244::-;1531:13:0;:11;:13::i;:::-;14251:15:19::1;14237:11;:29;14233:85;;;14289:18;;-1:-1:-1::0;;;14289:18:19::1;;;;;;;;;;;14233:85;14328:10;:24:::0;;;14367:30:::1;::::0;1128:25:49;;;14367:30:19::1;::::0;1116:2:49;1101:18;14367:30:19::1;982:177:49::0;21027:411:19;21109:17;21145:4;;21129:22;;;;;;;:::i;:::-;;;;;;;;;;21223:29;;;;;;;;;;;;;;;;;;;21129:22;-1:-1:-1;21129:22:19;;21161:15;;21223:29;;21129:22;21237:4;;;;;;21223:29;;21237:4;;;;21223:29;;;;;;;;;-1:-1:-1;21243:8:19;;-1:-1:-1;21223:13:19;;-1:-1:-1;;21223:29:19:i;:::-;21207:45;;21263:23;21280:5;21263:16;:23::i;:::-;21315:29;;-1:-1:-1;;;21315:29:19;;;;;10917:25:49;;;10958:18;;;10951:34;;;21297:15:19;;21315:4;-1:-1:-1;;;;;21315:10:19;;;;10890:18:49;;21315:29:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;21297:47;;21355:23;21372:5;21355:16;:23::i;:::-;21412:9;21394:37;21406:4;;21423:7;21394:37;;;;;;;;:::i;:::-;;;;;;;;21099:339;;;;21027:411;;;:::o;15811:185::-;15903:22;;;;;;15871:4;;15942:11;15919:4;15942:5;:11::i;:::-;:47;;;;-1:-1:-1;15957:32:19;;-1:-1:-1;;;15957:32:19;;;;;1128:25:49;;;15957:4:19;-1:-1:-1;;;;;15957:16:19;;;;1101:18:49;;15957:32:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;15935:54;15811:185;-1:-1:-1;;;15811:185:19:o;18044:266::-;18165:38;18184:7;18193:9;;18165:18;:38::i;:::-;18213:46;18235:23;:7;;:23;:::i;:::-;18213:21;:46::i;:::-;18269:34;18279:23;:7;;:23;:::i;:::-;18269:9;:34::i;31156:227::-;1531:13:0;:11;:13::i;:::-;31255:23:19::1;:50:::0;;-1:-1:-1;;;;;;31255:50:19::1;-1:-1:-1::0;;;;;31255:50:19;::::1;::::0;;::::1;::::0;;;31320:56:::1;::::0;160:51:49;;;31320:56:19::1;::::0;148:2:49;133:18;31320:56:19::1;14:203:49::0;18561:392:19;18693:7;10679:1;10657:12;;;;18693:7;10657:12;:::i;:::-;:19;;:23;:57;;;;-1:-1:-1;10712:1:19;10684:16;;;;;;;;:::i;:::-;-1:-1:-1;;;;;10684:30:19;;10657:57;10653:129;;;10737:34;;-1:-1:-1;;;10737:34:19;;;;;;;;;;;10653:129;10796:23;10806:12;:7;;:12;:::i;:::-;10796:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;10796:9:19;;-1:-1:-1;;;10796:23:19:i;:::-;10791:92;;10859:12;:7;;:12;:::i;:::-;10842:30;;-1:-1:-1;;;10842:30:19;;;;;;;;;:::i;:::-;;;;;;;;10791:92;9616:8;10896:7;:16;;;:44;10892:116;;;10980:16;10963:34;;-1:-1:-1;;;10963:34:19;;10980:16;;;;10963:34;;;1128:25:49;1101:18;;10963:34:19;982:177:49;10892:116:19;18716:42:::1;18739:7;18748:9;;18716:22;:42::i;:::-;18769:14;18786:21;:12;:7:::0;;:12:::1;:::i;:::-;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;;;-1:-1:-1;18786:19:19::1;::::0;-1:-1:-1;;;18786:21:19:i:1;:::-;18769:38;;18830:1;18821:6;:10;18817:53;;;18857:12;:7:::0;;:12:::1;:::i;18817:53::-;18881:30;18903:7;18881:21;:30::i;:::-;18921:25;18938:7;18921:16;:25::i;:::-;18706:247;18561:392:::0;;;;:::o;19357:422::-;19442:7;10679:1;10657:12;;;;19442:7;10657:12;:::i;:::-;:19;;:23;:57;;;;-1:-1:-1;10712:1:19;10684:16;;;;;;;;:::i;:::-;-1:-1:-1;;;;;10684:30:19;;10657:57;10653:129;;;10737:34;;-1:-1:-1;;;10737:34:19;;;;;;;;;;;10653:129;10796:23;10806:12;:7;;:12;:::i;10796:23::-;10791:92;;10859:12;:7;;:12;:::i;10791:92::-;9616:8;10896:7;:16;;;:44;10892:116;;;10980:16;10963:34;;-1:-1:-1;;;10963:34:19;;10980:16;;;;10963:34;;;1128:25:49;1101:18;;10963:34:19;982:177:49;10892:116:19;19479:19:::1;::::0;-1:-1:-1;;;;;19479:19:19::1;19465:10;:33;19461:105;;19521:34;;-1:-1:-1::0;;;19521:34:19::1;;;;;;;;;;;19461:105;19580:16;::::0;-1:-1:-1;;;;;19580:16:19::1;:31;19612:12;:7:::0;;:12:::1;:::i;:::-;19580:45;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;19575:76;;19634:17;;-1:-1:-1::0;;;19634:17:19::1;;;;;;;;;;;19575:76;19665:21;::::0;;;::::1;::::0;::::1;;:::i;:::-;19661:75;;;19695:41;;-1:-1:-1::0;;;19695:41:19::1;;;;;;;;;;;19661:75;19747:25;19764:7;19747:16;:25::i;:::-;19357:422:::0;;:::o;30176:171::-;30239:15;;30231:65;;30217:9;;-1:-1:-1;;;;;30239:15:19;;30269:21;;30217:9;30231:65;30217:9;30231:65;30269:21;30239:15;30231:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30216:80;;;30311:4;30306:34;;30324:16;;-1:-1:-1;;;30324:16:19;;;;;;;;;;;30306:34;30206:141;30176:171::o;16879:211::-;16961:7;16980:31;17014:25;17024:4;17030:8;17014:9;:25::i;:::-;17069:14;;;;17056:10;;16980:59;;-1:-1:-1;17056:27:19;;;:::i;16879:211::-;;;;;:::o;17449:157::-;11160:10;;11142:15;:28;11138:60;;;11179:19;;-1:-1:-1;;;11179:19:19;;;;;;;;;;;11138:60;17541:30:::1;17563:7;17541:21;:30::i;:::-;17581:18;17591:7;17581:9;:18::i;8695:22::-:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;2543:215:0:-;1531:13;:11;:13::i;:::-;-1:-1:-1;;;;;2627:22:0;::::1;2623:91;;2672:31;::::0;-1:-1:-1;;;2672:31:0;;2700:1:::1;2672:31;::::0;::::1;160:51:49::0;133:18;;2672:31:0::1;14:203:49::0;2623:91:0::1;2723:28;2742:8;2723:18;:28::i;1796:162::-:0;1684:7;1710:6;-1:-1:-1;;;;;1710:6:0;735:10:10;1855:23:0;1851:101;;1901:40;;-1:-1:-1;;;1901:40:0;;735:10:10;1901:40:0;;;160:51:49;133:18;;1901:40:0;14:203:49;1303:160:4;1412:43;;;-1:-1:-1;;;;;15175:32:49;;1412:43:4;;;15157:51:49;15224:18;;;;15217:34;;;1412:43:4;;;;;;;;;;15130:18:49;;;;1412:43:4;;;;;;;;-1:-1:-1;;;;;1412:43:4;-1:-1:-1;;;1412:43:4;;;1385:71;;1405:5;;1385:19;:71::i;2912:187:0:-;2985:16;3004:6;;-1:-1:-1;;;;;3020:17:0;;;-1:-1:-1;;;;;;3020:17:0;;;;;;3052:40;;3004:6;;;;;;;3052:40;;2985:16;3052:40;2975:124;2912:187;:::o;26787:246:19:-;26884:34;;-1:-1:-1;;;26884:34:19;;;;;1128:25:49;;;26847:15:19;;26884:4;-1:-1:-1;;;;;26884:16:19;;;;1101:18:49;;26884:34:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;26874:44;;26932:7;26943:1;26932:12;26928:60;;-1:-1:-1;;26967:10:19;;;26787:246::o;26928:60::-;27004:22;607:7:47;27004::19;:22;:::i;450:1830:48:-;632:15;;506:7;;555:1;;506:7;;;;658:1595;669:6;665:1;:10;658:1595;;;691:15;709:24;721:8;731:1;709:11;:24::i;:::-;691:42;-1:-1:-1;747:13:48;763:11;691:42;763:1;:11;:::i;:::-;747:27;;886:140;901:6;893:5;:14;:61;;;;;911:43;938:8;948:5;911:26;:43::i;:::-;886:140;;;983:28;995:8;1005:5;983:11;:28::i;:::-;974:37;;;;:::i;:::-;;;886:140;;;1142:6;1134:5;:14;:53;;;;;1152:35;1171:8;1181:5;1152:18;:35::i;:::-;1127:740;;;1253:28;1265:8;1275:5;1253:11;:28::i;:::-;1244:37;;;;:::i;:::-;;;1368:6;1360:5;:14;1356:497;;;1398:19;1420:28;1432:8;1442:5;1420:11;:28::i;:::-;1398:50;-1:-1:-1;1470:20:48;1398:50;1470:20;;:::i;:::-;;;1601:156;1616:6;1608:5;:14;:61;;;;;1626:43;1653:8;1663:5;1626:26;:43::i;:::-;1601:156;;;1706:28;1718:8;1728:5;1706:11;:28::i;:::-;1697:37;;;;:::i;:::-;;;1601:156;;;1376:399;1127:740;;1356:497;1967:33;1988:8;1998:1;1967:20;:33::i;:::-;:51;;;;;2012:6;2004:5;:14;1967:51;:92;;;;;2022:37;2043:8;2053:5;2022:20;:37::i;:::-;1963:168;;;2088:28;2100:8;2110:5;2088:11;:28::i;:::-;2079:37;;;;:::i;:::-;;;1963:168;2214:5;;;;:::i;:::-;;;;2237;2233:9;;677:1576;;658:1595;;;-1:-1:-1;2270:3:48;;450:1830;-1:-1:-1;;;;450:1830:48:o;21632:193:19:-;21708:5;21696:9;:17;21692:74;;;21736:19;;-1:-1:-1;;;21736:19:19;;;;;;;;;;;21692:74;21780:38;;1128:25:49;;;21800:10:19;;21780:38;;1116:2:49;1101:18;21780:38:19;;;;;;;21632:193;:::o;28595:246::-;2356:21:11;:19;:21::i;:::-;28684:5:19::1;28672:9;:17;28668:167;;;28706:9;28728:10;28753:17;28765:5:::0;28753:9:::1;:17;:::i;:::-;28720:56;::::0;::::1;::::0;;;;;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;28705:71;;;28795:4;28790:34;;28808:16;;-1:-1:-1::0;;;28808:16:19::1;;;;;;;;;;;28790:34;28691:144;28668:167;2398:20:11::0;1713:1;2924:21;;2744:208;22720:1130:19;22836:20;22883:23;:7;;:23;:::i;:::-;:28;;;;:::i;:::-;22925:23;:7;;:23;:::i;:::-;:29;;;;;;;;;:::i;:::-;22968:23;:7;;:23;:::i;:::-;:32;;;23014:23;:7;;:23;:::i;:::-;:32;;;;;;;;;:::i;:::-;23060:23;:7;;:23;:::i;:::-;:28;;;;;;;:::i;:::-;23102:23;:7;;:23;:::i;:::-;:37;;;;;;;;;:::i;:::-;23153:23;:7;;:23;:::i;:::-;:32;;;;;;;;;:::i;:::-;23199:7;:16;;;23229:7;:24;;;22859:404;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;22836:427;;23273:19;23295:36;23323:7;23295:27;:36::i;:::-;23346:27;;;;:14;:27;;;;;;23273:58;;-1:-1:-1;23346:27:19;;23342:62;;;23382:22;;-1:-1:-1;;;23382:22:19;;;;;;;;;;;23342:62;23445:10;23418:38;;;;:26;:38;;;;23478:24;23418:38;;;23457:16;;;;23418:56;;;;;;;;;;23478:24;;;;-1:-1:-1;23414:148:19;;23525:26;;-1:-1:-1;;;23525:26:19;;;;;;;;;;;23414:148;23572:14;23589:46;23612:11;23625:9;;23589:22;:46::i;:::-;23572:63;-1:-1:-1;;;;;;23650:20:19;;;;:53;;-1:-1:-1;23684:19:19;;-1:-1:-1;;;;;23674:29:19;;;23684:19;;23674:29;;23650:53;23646:84;;;23712:18;;-1:-1:-1;;;23712:18:19;;;;;;;;;;;23646:84;23741:27;;;;:14;:27;;;;;;;;:34;;-1:-1:-1;;23741:34:19;23771:4;23741:34;;;23812:10;23785:38;;:26;:38;;;;;23824:16;;;;23785:56;;;;;;;:58;;;;;;:::i;:::-;;;;;;22826:1024;;;22720:1130;;;:::o;21831:274::-;21924:16;;-1:-1:-1;;;;;21924:16:19;:31;21956:12;:7;;:12;:::i;:::-;21924:45;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;21920:72;;;21978:14;;-1:-1:-1;;;21978:14:19;;;;;;;;;;;21920:72;22023:10;22006:13;;;;;;;;:::i;:::-;-1:-1:-1;;;;;22006:27:19;;;:52;;;;-1:-1:-1;22037:21:19;;;;;;;;:::i;:::-;22002:96;;;22067:31;;-1:-1:-1;;;22067:31:19;;;;;;;;;;;20141:269;20221:7;10679:1;10657:12;;;;20221:7;10657:12;:::i;:::-;:19;;:23;:57;;;;-1:-1:-1;10712:1:19;10684:16;;;;;;;;:::i;:::-;-1:-1:-1;;;;;10684:30:19;;10657:57;10653:129;;;10737:34;;-1:-1:-1;;;10737:34:19;;;;;;;;;;;10653:129;10796:23;10806:12;:7;;:12;:::i;10796:23::-;10791:92;;10859:12;:7;;:12;:::i;10791:92::-;9616:8;10896:7;:16;;;:44;10892:116;;;10980:16;10963:34;;-1:-1:-1;;;10963:34:19;;10980:16;;;;10963:34;;;1128:25:49;1101:18;;10963:34:19;982:177:49;10892:116:19;20240:13:::1;20256:45;20270:12;:7:::0;;:12:::1;:::i;:::-;20256:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;;;-1:-1:-1;;;;20284:16:19::1;::::0;::::1;;20256:13;:45::i;:::-;20240:61;;20312:23;20329:5;20312:16;:23::i;:::-;20345:25;20362:7;20345:16;:25::i;:::-;20380:23;20397:5;20380:16;:23::i;24364:872::-:0;24475:20;24522:12;:7;;:12;:::i;:::-;24548:13;;;;;;;;:::i;:::-;24575:16;;;;24605;;;;;;;;:::i;:::-;24635:12;;;;:7;:12;:::i;:::-;24661:21;;;;;;;;:::i;:::-;24696:16;;;;;;;;:::i;:::-;24498:224;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;24475:247;;24732:19;24754:36;24782:7;24754:27;:36::i;:::-;24805;;;;:23;:36;;;;;;24732:58;;-1:-1:-1;24805:36:19;;24801:79;;;24850:30;;-1:-1:-1;;;24850:30:19;;;;;;;;;;;24801:79;24913:10;24894:30;;;;:18;:30;;;;;;;;:35;24890:70;;24938:22;;-1:-1:-1;;;24938:22:19;;;;;;;;;;;24890:70;24971:14;24988:46;25011:11;25024:9;;24988:22;:46::i;:::-;24971:63;-1:-1:-1;;;;;;25049:20:19;;;;:57;;-1:-1:-1;25083:23:19;;-1:-1:-1;;;;;25073:33:19;;;25083:23;;25073:33;;25049:57;25045:88;;;25115:18;;-1:-1:-1;;;25115:18:19;;;;;;;;;;;25045:88;25144:36;;;;:23;:36;;;;;;;;:43;;-1:-1:-1;;25144:43:19;25183:4;25144:43;;;25216:10;25197:30;;:18;:30;;;;;:32;;25144:43;25197:32;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;24465:771;;;24364:872;;;:::o;27530:879::-;27609:15;-1:-1:-1;;;;;27627:4:19;:23;;27688:12;:7;;:12;:::i;:::-;27672:30;;;;;;;:::i;:::-;;;;;;;;;;;;27705:13;;;;;;;;:::i;:::-;27720:16;;;;27738;;;;;;;;:::i;:::-;27627:140;;-1:-1:-1;;;;;;27627:140:19;;;;;;;;;;19076:25:49;;;;-1:-1:-1;;;;;19137:32:49;;;19117:18;;;19110:60;19186:18;;;19179:34;;;;19249:32;19229:18;;;19222:60;27756:1:19;19298:19:49;;;19291:60;19048:19;;27627:140:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;27609:158;-1:-1:-1;27804:1:19;27782:12;;;;:7;:12;:::i;:::-;:19;;:23;27778:129;;;27821:75;27833:16;;;;;;;;:::i;:::-;27867:12;:7;;:12;:::i;:::-;27851:30;;;;;;;:::i;:::-;;;;;;;;;27883:12;;;;:7;:12;:::i;:::-;27821:11;:75::i;:::-;27921:21;;;;;;;;:::i;:::-;27917:113;;;27958:61;27976:12;:7;;:12;:::i;:::-;27958:61;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;27990:16:19;;-1:-1:-1;;;27990:16:19;;;;;;;:::i;:::-;28008:10;27958:17;:61::i;:::-;28160:13;;;;;;;;:::i;:::-;-1:-1:-1;;;;;28099:84:19;28144:12;:7;;:12;:::i;:::-;28128:30;;;;;;;:::i;:::-;;;;;;;;;28099:84;28114:12;:7;;:12;:::i;:::-;28175:7;28099:84;;;;;;;;:::i;:::-;;;;;;;;28225:1;28197:16;;;;;;;;:::i;:::-;-1:-1:-1;;;;;28197:30:19;;28193:210;;28353:16;;;;;;;;:::i;:::-;-1:-1:-1;;;;;28248:144:19;28338:13;;;;;;;;:::i;:::-;-1:-1:-1;;;;;28248:144:19;28322:12;:7;;:12;:::i;:::-;28306:30;;;;;;;:::i;:::-;;;;;;;;;28248:144;28292:12;:7;;:12;:::i;:::-;28371:7;28248:144;;;;;;;;:::i;:::-;;;;;;;;27599:810;27530:879;:::o;4059:629:4:-;4478:23;4504:33;-1:-1:-1;;;;;4504:27:4;;4532:4;4504:27;:33::i;:::-;4478:59;;4551:10;:17;4572:1;4551:22;;:57;;;;;4589:10;4578:30;;;;;;;;;;;;:::i;:::-;4577:31;4551:57;4547:135;;;4631:40;;-1:-1:-1;;;4631:40:4;;-1:-1:-1;;;;;178:32:49;;4631:40:4;;;160:51:49;133:18;;4631:40:4;14:203:49;2369:956:48;2450:7;2469;2485:8;2494:5;2485:15;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;2520:4:48;2516:8;;2512:807;;;2547:1;2540:8;;;;;2512:807;2601:4;2597:1;:8;;;:39;;;;-1:-1:-1;2621:15:48;;2609:9;:5;2617:1;2609:9;:::i;:::-;:27;2597:39;:84;;;;-1:-1:-1;2646:8:48;2655:9;:5;2663:1;2655:9;:::i;:::-;2646:19;;;;;;;;:::i;:::-;;;;;;;;;2640:26;;2669:4;2640:33;:41;;2677:4;2640:41;2597:84;2593:726;;;2704:1;2697:8;;;;;2593:726;2763:4;2759:1;:8;;;:39;;;;-1:-1:-1;2783:15:48;;2771:9;:5;2779:1;2771:9;:::i;:::-;:27;2759:39;:84;;;;-1:-1:-1;2808:8:48;2817:9;:5;2825:1;2817:9;:::i;:::-;2808:19;;;;;;;;:::i;:::-;;;;;;;;;2802:26;;2831:4;2802:33;:41;;2839:4;2802:41;2759:84;:145;;;;-1:-1:-1;2869:8:48;2878:9;:5;2886:1;2878:9;:::i;:::-;2869:19;;;;;;;;:::i;:::-;;;;;;;;;2863:26;;2892:4;2863:33;:41;;2900:4;2863:41;2759:145;2742:577;;;2936:1;2929:8;;;;;2742:577;2995:4;2991:1;:8;;;:39;;;;-1:-1:-1;3015:15:48;;3003:9;:5;3011:1;3003:9;:::i;:::-;:27;2991:39;:84;;;;-1:-1:-1;3040:8:48;3049:9;:5;3057:1;3049:9;:::i;:::-;3040:19;;;;;;;;:::i;:::-;;;;;;;;;3034:26;;3063:4;3034:33;:41;;3071:4;3034:41;2991:84;:145;;;;-1:-1:-1;3101:8:48;3110:9;:5;3118:1;3110:9;:::i;:::-;3101:19;;;;;;;;:::i;:::-;;;;;;;;;3095:26;;3124:4;3095:33;:41;;3132:4;3095:41;2991:145;:190;;;;-1:-1:-1;3146:8:48;3155:9;:5;3163:1;3155:9;:::i;:::-;3146:19;;;;;;;;:::i;:::-;;;;;;;;;3140:26;;3169:4;3140:33;:41;;3177:4;3140:41;2991:190;2974:345;;;3213:1;3206:8;;;;;2974:345;3291:17;;-1:-1:-1;;;3291:17:48;;;;;;;;;;;3760:2267;3856:4;3872:7;3888:8;3897:5;3888:15;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;3995:4:48;3990:9;;;:22;;;4003:1;:9;;4008:4;4003:9;3990:22;3986:64;;;4035:4;4028:11;;;;;3986:64;4115:1;:9;;4120:4;4115:9;:40;;;;-1:-1:-1;4140:15:48;;4128:9;:5;4136:1;4128:9;:::i;:::-;:27;4115:40;4111:322;;;4171:8;4188;4197:9;:5;4205:1;4197:9;:::i;:::-;4188:19;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;4222:8:48;4239;4248:9;:5;4256:1;4248:9;:::i;:::-;4239:19;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;4343:4:48;4233:26;4337:10;;;:40;;;;;4352:2;:10;;4358:4;4352:10;:24;;;;4366:2;:10;;4372:4;4366:10;4352:24;4333:90;;;4404:4;4397:11;;;;;;;4333:90;4157:276;;4111:322;4511:1;:9;;4516:4;4511:9;:40;;;;-1:-1:-1;4536:15:48;;4524:9;:5;4532:1;4524:9;:::i;:::-;:27;4511:40;4507:551;;;4567:8;4584;4593:9;:5;4601:1;4593:9;:::i;:::-;4584:19;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;4618:8:48;4635;4644:9;:5;4652:1;4644:9;:::i;:::-;4635:19;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;4669:8:48;4686;4695:9;:5;4703:1;4695:9;:::i;:::-;4686:19;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;4817:4:48;4680:26;4811:10;;;:24;;;;;4825:2;:10;;4831:4;4825:10;4811:24;:54;;;;;4846:4;4840:2;:10;;;;:24;;;;;4860:4;4854:2;:10;;;;4840:24;4810:143;;;;4914:2;:10;;4920:4;4914:10;:24;;;;;4928:2;:10;;4934:4;4928:10;4914:24;:38;;;;;4942:2;:10;;4948:4;4942:10;4914:38;4789:259;;;5029:4;5022:11;;;;;;;;4789:259;4553:505;;;4507:551;5124:1;:9;;5129:4;5124:9;:40;;;;-1:-1:-1;5149:15:48;;5137:9;:5;5145:1;5137:9;:::i;:::-;:27;5124:40;5120:246;;;5180:8;5197;5206:9;:5;5214:1;5206:9;:::i;:::-;5197:19;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;5231:8:48;5248;5257:9;:5;5265:1;5257:9;:::i;:::-;5248:19;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;5292:4:48;5242:26;5286:10;;;:24;;;;;5300:2;:10;;5306:4;5300:10;5286:24;5282:74;;;5337:4;5330:11;;;;;;;5282:74;5166:200;;5120:246;5437:1;:9;;5442:4;5437:9;:40;;;;-1:-1:-1;5462:15:48;;5450:9;:5;5458:1;5450:9;:::i;:::-;:27;5437:40;5433:246;;;5493:8;5510;5519:9;:5;5527:1;5519:9;:::i;:::-;5510:19;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;5544:8:48;5561;5570:9;:5;5578:1;5570:9;:::i;:::-;5561:19;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;5605:4:48;5555:26;5599:10;;;:24;;;;;5613:2;:10;;5619:4;5613:10;5599:24;5595:74;;;5650:4;5643:11;;;;;;;5595:74;5479:200;;5433:246;5802:1;:9;;5807:4;5802:9;:40;;;;-1:-1:-1;5827:15:48;;5815:9;:5;5823:1;5815:9;:::i;:::-;:27;5802:40;:71;;;;-1:-1:-1;5846:8:48;5855:9;:5;5863:1;5855:9;:::i;:::-;5846:19;;;;;;;;:::i;:::-;;;;;;-1:-1:-1;;;;;;5846:19:48;-1:-1:-1;;;5846:27:48;5802:71;:102;;;;-1:-1:-1;;;;5877:8:48;5886:9;:5;5894:1;5886:9;:::i;:::-;5877:19;;;;;;;;:::i;:::-;;;;;-1:-1:-1;;;;;;5877:19:48;:27;;5802:102;:149;;;;-1:-1:-1;;;;5924:8:48;5933:9;:5;5941:1;5933:9;:::i;:::-;5924:19;;;;;;;;:::i;:::-;;;;;-1:-1:-1;;;;;;5924:19:48;:27;;5802:149;5785:213;;;5983:4;5976:11;;;;;5785:213;-1:-1:-1;6015:5:48;;3760:2267;-1:-1:-1;;;3760:2267:48:o;3408:274::-;3496:4;3533:8;3542:5;3533:15;;;;;;;;:::i;:::-;;;;;;-1:-1:-1;;;;;;3533:15:48;-1:-1:-1;;;3533:23:48;:54;;;;-1:-1:-1;3572:15:48;;3560:9;:5;3568:1;3560:9;:::i;:::-;:27;3533:54;:85;;;;-1:-1:-1;3591:8:48;3600:9;:5;3608:1;3600:9;:::i;:::-;3591:19;;;;;;;;:::i;:::-;;;;;;-1:-1:-1;;;;;;3591:19:48;-1:-1:-1;;;3591:27:48;3533:85;:132;;;;-1:-1:-1;3638:8:48;3647:9;:5;3655:1;3647:9;:::i;:::-;3638:19;;;;;;;;:::i;:::-;;;;;;-1:-1:-1;;;;;;3638:19:48;-1:-1:-1;;;3638:27:48;3512:163;3408:274;-1:-1:-1;;;3408:274:48:o;6127:276::-;6217:4;6254:8;6263:5;6254:15;;;;;;;;:::i;:::-;;;;;;-1:-1:-1;;;;;;6254:15:48;-1:-1:-1;;;6254:23:48;:54;;;;-1:-1:-1;6293:15:48;;6281:9;:5;6289:1;6281:9;:::i;:::-;:27;6254:54;:85;;;;-1:-1:-1;6312:8:48;6321:9;:5;6329:1;6321:9;:::i;:::-;6312:19;;;;;;;;:::i;:::-;;;;;;-1:-1:-1;;;;;;6312:19:48;-1:-1:-1;;;6312:27:48;6254:85;:132;;;;-1:-1:-1;6359:8:48;6368:9;:5;6376:1;6368:9;:::i;:::-;6359:19;;;;;;;;:::i;:::-;;;;;;-1:-1:-1;;;;;;6359:19:48;-1:-1:-1;;;6359:27:48;;6127:276;-1:-1:-1;;;6127:276:48:o;2431:307:11:-;1755:1;2558:7;;:18;2554:86;;2599:30;;-1:-1:-1;;;2599:30:11;;;;;;;;;;;2554:86;1755:1;2714:7;:17;2431:307::o;25242:198:19:-;25324:7;25423;25413:18;;;;;;25360:72;;;;;;;19736:66:49;19724:79;;19828:2;19819:12;;19812:28;;;;19865:2;19856:12;;19494:380;25360:72:19;;;;;;;;;;;;;25350:83;;;;;;25343:90;;25242:198;;;:::o;25446:172::-;25548:7;25574:37;25588:11;25601:9;;25574:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;25574:13:19;;-1:-1:-1;;;25574:37:19:i;29286:307::-;29418:33;;;29435:8;29418:33;;;;20036:19:49;;;;20071:12;;;20064:28;;;29418:33:19;;;;;;;;;20108:12:49;;;29418:33:19;;;;29408:44;;;;;-1:-1:-1;;;29539:47:19;;;29513:15;;-1:-1:-1;;;;;29539:31:19;;;;;:47;;29408:44;;29581:4;;;;29539:47;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;29539:47:19;;;;;;;;;;;;:::i;:::-;;29379:214;;29286:307;;;;:::o;29863:197::-;29962:16;;30023:29;;-1:-1:-1;;;;;29962:16:19;;;;:31;;29994:10;;30006:5;;30013:8;;30023:29;;30037:4;;30043:8;;30023:29;;;:::i;:::-;;;;;;;;;;;;;29962:91;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;29863:197;;;:::o;2705:151:9:-;2780:12;2811:38;2833:6;2841:4;2847:1;2811:21;:38::i;3702:255:13:-;3780:7;3800:17;3819:18;3839:16;3859:27;3870:4;3876:9;3859:10;:27::i;:::-;3799:87;;;;;;3896:28;3908:5;3915:8;3896:11;:28::i;3180:392:9:-;3279:12;3331:5;3307:21;:29;3303:108;;;3359:41;;-1:-1:-1;;;3359:41:9;;3394:4;3359:41;;;160:51:49;133:18;;3359:41:9;14:203:49;3303:108:9;3421:12;3435:23;3462:6;-1:-1:-1;;;;;3462:11:9;3481:5;3488:4;3462:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3420:73;;;;3510:55;3537:6;3545:7;3554:10;3510:26;:55::i;:::-;3503:62;3180:392;-1:-1:-1;;;;;;3180:392:9:o;2129:766:13:-;2210:7;2219:12;2233:7;2256:9;:16;2276:2;2256:22;2252:637;;2592:4;2577:20;;2571:27;2641:4;2626:20;;2620:27;2698:4;2683:20;;2677:27;2294:9;2669:36;2739:25;2750:4;2669:36;2571:27;2620;2739:10;:25::i;:::-;2732:32;;;;;;;;;;;2252:637;-1:-1:-1;;2860:16:13;;2811:1;;-1:-1:-1;2815:35:13;;2252:637;2129:766;;;;;:::o;7196:532::-;7291:20;7282:5;:29;;;;;;;;:::i;:::-;;7278:444;;7196:532;;:::o;7278:444::-;7387:29;7378:5;:38;;;;;;;;:::i;:::-;;7374:348;;7439:23;;-1:-1:-1;;;7439:23:13;;;;;;;;;;;7374:348;7492:35;7483:5;:44;;;;;;;;:::i;:::-;;7479:243;;7550:46;;-1:-1:-1;;;7550:46:13;;;;;1128:25:49;;;1101:18;;7550:46:13;982:177:49;7479:243:13;7626:30;7617:5;:39;;;;;;;;:::i;:::-;;7613:109;;7679:32;;-1:-1:-1;;;7679:32:13;;;;;1128:25:49;;;1101:18;;7679:32:13;982:177:49;4625:582:9;4769:12;4798:7;4793:408;;4821:19;4829:10;4821:7;:19::i;:::-;4793:408;;;5045:17;;:22;:49;;;;-1:-1:-1;;;;;;5071:18:9;;;:23;5045:49;5041:119;;;5121:24;;-1:-1:-1;;;5121:24:9;;-1:-1:-1;;;;;178:32:49;;5121:24:9;;;160:51:49;133:18;;5121:24:9;14:203:49;5041:119:9;-1:-1:-1;5180:10:9;5173:17;;5140:1530:13;5266:7;;;6199:66;6186:79;;6182:164;;;-1:-1:-1;6297:1:13;;-1:-1:-1;6301:30:13;;-1:-1:-1;6333:1:13;6281:54;;6182:164;6457:24;;;6440:14;6457:24;;;;;;;;;24832:25:49;;;24905:4;24893:17;;24873:18;;;24866:45;;;;24927:18;;;24920:34;;;24970:18;;;24963:34;;;6457:24:13;;24804:19:49;;6457:24:13;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;6457:24:13;;-1:-1:-1;;6457:24:13;;;-1:-1:-1;;;;;;;6495:20:13;;6491:113;;-1:-1:-1;6547:1:13;;-1:-1:-1;6551:29:13;;-1:-1:-1;6547:1:13;;-1:-1:-1;6531:62:13;;6491:113;6622:6;-1:-1:-1;6630:20:13;;-1:-1:-1;6630:20:13;;-1:-1:-1;5140:1530:13;;;;;;;;;:::o;5743:516:9:-;5874:17;;:21;5870:383;;6102:10;6096:17;6158:15;6145:10;6141:2;6137:19;6130:44;5870:383;6225:17;;-1:-1:-1;;;6225:17:9;;;;;;;;;;;222:131:49;-1:-1:-1;;;;;297:31:49;;287:42;;277:70;;343:1;340;333:12;358:247;417:6;470:2;458:9;449:7;445:23;441:32;438:52;;;486:1;483;476:12;438:52;525:9;512:23;544:31;569:5;544:31;:::i;610:367::-;678:6;686;739:2;727:9;718:7;714:23;710:32;707:52;;;755:1;752;745:12;707:52;794:9;781:23;813:31;838:5;813:31;:::i;:::-;863:5;941:2;926:18;;;;913:32;;-1:-1:-1;;;610:367:49:o;1437:180::-;1496:6;1549:2;1537:9;1528:7;1524:23;1520:32;1517:52;;;1565:1;1562;1555:12;1517:52;-1:-1:-1;1588:23:49;;1437:180;-1:-1:-1;1437:180:49:o;2092:508::-;2169:6;2177;2185;2238:2;2226:9;2217:7;2213:23;2209:32;2206:52;;;2254:1;2251;2244:12;2206:52;2293:9;2280:23;2312:31;2337:5;2312:31;:::i;:::-;2362:5;-1:-1:-1;2419:2:49;2404:18;;2391:32;2432:33;2391:32;2432:33;:::i;:::-;2092:508;;2484:7;;-1:-1:-1;;;2564:2:49;2549:18;;;;2536:32;;2092:508::o;3028:127::-;3089:10;3084:3;3080:20;3077:1;3070:31;3120:4;3117:1;3110:15;3144:4;3141:1;3134:15;3160:275;3231:2;3225:9;3296:2;3277:13;;-1:-1:-1;;3273:27:49;3261:40;;-1:-1:-1;;;;;3316:34:49;;3352:22;;;3313:62;3310:88;;;3378:18;;:::i;:::-;3414:2;3407:22;3160:275;;-1:-1:-1;3160:275:49:o;3440:187::-;3489:4;-1:-1:-1;;;;;3514:6:49;3511:30;3508:56;;;3544:18;;:::i;:::-;-1:-1:-1;3610:2:49;3589:15;-1:-1:-1;;3585:29:49;3616:4;3581:40;;3440:187::o;3632:488::-;3675:5;3728:3;3721:4;3713:6;3709:17;3705:27;3695:55;;3746:1;3743;3736:12;3695:55;3786:6;3773:20;3817:53;3833:36;3862:6;3833:36;:::i;:::-;3817:53;:::i;:::-;3895:6;3886:7;3879:23;3949:3;3942:4;3933:6;3925;3921:19;3917:30;3914:39;3911:59;;;3966:1;3963;3956:12;3911:59;4031:6;4024:4;4016:6;4012:17;4005:4;3996:7;3992:18;3979:59;4087:1;4058:20;;;4080:4;4054:31;4047:42;;;;4062:7;3632:488;-1:-1:-1;;;3632:488:49:o;4125:436::-;4203:6;4211;4264:2;4252:9;4243:7;4239:23;4235:32;4232:52;;;4280:1;4277;4270:12;4232:52;4320:9;4307:23;-1:-1:-1;;;;;4345:6:49;4342:30;4339:50;;;4385:1;4382;4375:12;4339:50;4408;4450:7;4441:6;4430:9;4426:22;4408:50;:::i;:::-;4398:60;4527:2;4512:18;;;;4499:32;;-1:-1:-1;;;;4125:436:49:o;4864:322::-;4933:6;4986:2;4974:9;4965:7;4961:23;4957:32;4954:52;;;5002:1;4999;4992:12;4954:52;5042:9;5029:23;-1:-1:-1;;;;;5067:6:49;5064:30;5061:50;;;5107:1;5104;5097:12;5061:50;5130;5172:7;5163:6;5152:9;5148:22;5130:50;:::i;5422:348::-;5474:8;5484:6;5538:3;5531:4;5523:6;5519:17;5515:27;5505:55;;5556:1;5553;5546:12;5505:55;-1:-1:-1;5579:20:49;;-1:-1:-1;;;;;5611:30:49;;5608:50;;;5654:1;5651;5644:12;5608:50;5691:4;5683:6;5679:17;5667:29;;5743:3;5736:4;5727:6;5719;5715:19;5711:30;5708:39;5705:59;;;5760:1;5757;5750:12;5705:59;5422:348;;;;;:::o;5775:525::-;5855:6;5863;5871;5924:2;5912:9;5903:7;5899:23;5895:32;5892:52;;;5940:1;5937;5930:12;5892:52;5980:9;5967:23;-1:-1:-1;;;;;6005:6:49;6002:30;5999:50;;;6045:1;6042;6035:12;5999:50;6084:59;6135:7;6126:6;6115:9;6111:22;6084:59;:::i;:::-;6162:8;;6058:85;;-1:-1:-1;6266:2:49;6251:18;;;;6238:32;;5775:525;-1:-1:-1;;;;5775:525:49:o;6305:707::-;6428:6;6436;6444;6497:2;6485:9;6476:7;6472:23;6468:32;6465:52;;;6513:1;6510;6503:12;6465:52;6553:9;6540:23;-1:-1:-1;;;;;6578:6:49;6575:30;6572:50;;;6618:1;6615;6608:12;6572:50;6641:22;;6697:2;6679:16;;;6675:25;6672:45;;;6713:1;6710;6703:12;6672:45;6736:2;-1:-1:-1;6791:2:49;6776:18;;6763:32;-1:-1:-1;;;;;6807:32:49;;6804:52;;;6852:1;6849;6842:12;6804:52;6891:61;6944:7;6933:8;6922:9;6918:24;6891:61;:::i;:::-;6305:707;;6971:8;;-1:-1:-1;6865:87:49;;-1:-1:-1;;;;6305:707:49:o;7480:164::-;7548:5;7593:3;7584:6;7579:3;7575:16;7571:26;7568:46;;;7610:1;7607;7600:12;7568:46;-1:-1:-1;7632:6:49;7480:164;-1:-1:-1;7480:164:49:o;7649:676::-;7763:6;7771;7779;7832:2;7820:9;7811:7;7807:23;7803:32;7800:52;;;7848:1;7845;7838:12;7800:52;7888:9;7875:23;-1:-1:-1;;;;;7913:6:49;7910:30;7907:50;;;7953:1;7950;7943:12;7907:50;7976:75;8043:7;8034:6;8023:9;8019:22;7976:75;:::i;:::-;7966:85;;;8104:2;8093:9;8089:18;8076:32;-1:-1:-1;;;;;8123:8:49;8120:32;8117:52;;;8165:1;8162;8155:12;8330:372;8424:6;8477:2;8465:9;8456:7;8452:23;8448:32;8445:52;;;8493:1;8490;8483:12;8445:52;8533:9;8520:23;-1:-1:-1;;;;;8558:6:49;8555:30;8552:50;;;8598:1;8595;8588:12;8552:50;8621:75;8688:7;8679:6;8668:9;8664:22;8621:75;:::i;8707:300::-;8760:3;8798:5;8792:12;8825:6;8820:3;8813:19;8881:6;8874:4;8867:5;8863:16;8856:4;8851:3;8847:14;8841:47;8933:1;8926:4;8917:6;8912:3;8908:16;8904:27;8897:38;8996:4;8989:2;8985:7;8980:2;8972:6;8968:15;8964:29;8959:3;8955:39;8951:50;8944:57;;;8707:300;;;;:::o;9012:231::-;9161:2;9150:9;9143:21;9124:4;9181:56;9233:2;9222:9;9218:18;9210:6;9181:56;:::i;9430:373::-;9635:2;9624:9;9617:21;9598:4;9655:56;9707:2;9696:9;9692:18;9684:6;9655:56;:::i;:::-;9742:2;9727:18;;9720:34;;;;-1:-1:-1;9785:2:49;9770:18;9763:34;9647:64;9430:373;-1:-1:-1;9430:373:49:o;9808:654::-;9901:6;9961:2;9949:9;9940:7;9936:23;9932:32;9976:2;9973:22;;;9991:1;9988;9981:12;9973:22;-1:-1:-1;10060:2:49;10054:9;;;10090:15;;-1:-1:-1;;;;;10120:34:49;;10156:22;;;10117:62;10114:88;;;10182:18;;:::i;:::-;10218:2;10211:22;10274:16;;10299:21;;10386:2;10371:18;;;10365:25;10406:15;;;10399:32;;;;-1:-1:-1;10306:6:49;9808:654;-1:-1:-1;9808:654:49:o;10467:271::-;10650:6;10642;10637:3;10624:33;10606:3;10676:16;;10701:13;;;10676:16;10467:271;-1:-1:-1;10467:271:49:o;10996:230::-;11066:6;11119:2;11107:9;11098:7;11094:23;11090:32;11087:52;;;11135:1;11132;11125:12;11087:52;-1:-1:-1;11180:16:49;;10996:230;-1:-1:-1;10996:230:49:o;11231:267::-;11320:6;11315:3;11308:19;11372:6;11365:5;11358:4;11353:3;11349:14;11336:43;-1:-1:-1;11424:1:49;11399:16;;;11417:4;11395:27;;;11388:38;;;;11480:2;11459:15;;;-1:-1:-1;;11455:29:49;11446:39;;;11442:50;;11231:267::o;11503:318::-;11690:2;11679:9;11672:21;11653:4;11710:62;11768:2;11757:9;11753:18;11745:6;11737;11710:62;:::i;:::-;11702:70;;11808:6;11803:2;11792:9;11788:18;11781:34;11503:318;;;;;;:::o;11826:118::-;11912:5;11905:13;11898:21;11891:5;11888:32;11878:60;;11934:1;11931;11924:12;11949:245;12016:6;12069:2;12057:9;12048:7;12044:23;12040:32;12037:52;;;12085:1;12082;12075:12;12037:52;12117:9;12111:16;12136:28;12158:5;12136:28;:::i;12199:333::-;12300:4;12358:11;12345:25;12452:3;12448:8;12437;12421:14;12417:29;12413:44;12393:18;12389:69;12379:97;;12472:1;12469;12462:12;12379:97;12493:33;;;;;12199:333;-1:-1:-1;;12199:333:49:o;12537:556::-;12641:4;12647:6;12707:11;12694:25;12801:2;12797:7;12786:8;12770:14;12766:29;12762:43;12742:18;12738:68;12728:96;;12820:1;12817;12810:12;12728:96;12847:33;;12899:20;;;-1:-1:-1;;;;;;12931:30:49;;12928:50;;;12974:1;12971;12964:12;12928:50;13007:4;12995:17;;-1:-1:-1;13058:1:49;13054:14;;;13038;13034:35;13024:46;;13021:66;;;13083:1;13080;13073:12;13098:522;13176:4;13182:6;13242:11;13229:25;13336:2;13332:7;13321:8;13305:14;13301:29;13297:43;13277:18;13273:68;13263:96;;13355:1;13352;13345:12;13263:96;13382:33;;13434:20;;;-1:-1:-1;;;;;;13466:30:49;;13463:50;;;13509:1;13506;13499:12;13463:50;13542:4;13530:17;;-1:-1:-1;13573:14:49;13569:27;;;13559:38;;13556:58;;;13610:1;13607;13600:12;13625:247;13784:2;13773:9;13766:21;13747:4;13804:62;13862:2;13851:9;13847:18;13839:6;13831;13804:62;:::i;13877:241::-;13933:6;13986:2;13974:9;13965:7;13961:23;13957:32;13954:52;;;14002:1;13999;13992:12;13954:52;14041:9;14028:23;14060:28;14082:5;14060:28;:::i;14333:127::-;14394:10;14389:3;14385:20;14382:1;14375:31;14425:4;14422:1;14415:15;14449:4;14446:1;14439:15;14465:128;14532:9;;;14553:11;;;14550:37;;;14567:18;;:::i;14598:380::-;14677:1;14673:12;;;;14720;;;14741:61;;14795:4;14787:6;14783:17;14773:27;;14741:61;14848:2;14840:6;14837:14;14817:18;14814:38;14811:161;;14894:10;14889:3;14885:20;14882:1;14875:31;14929:4;14926:1;14919:15;14957:4;14954:1;14947:15;15262:125;15327:9;;;15348:10;;;15345:36;;;15361:18;;:::i;15392:135::-;15431:3;15452:17;;;15449:43;;15472:18;;:::i;:::-;-1:-1:-1;15519:1:49;15508:13;;15392:135::o;15532:1031::-;15609:3;15640;15664:6;15659:3;15652:19;15696:4;15691:3;15687:14;15680:21;;15754:4;15744:6;15741:1;15737:14;15730:5;15726:26;15722:37;15782:5;15805:1;15815:722;15829:6;15826:1;15823:13;15815:722;;;15894:16;;;-1:-1:-1;;15890:30:49;15878:43;;15960:20;;16035:14;16031:26;;;-1:-1:-1;;16027:40:49;16003:65;;15993:93;;16082:1;16079;16072:12;15993:93;16114:30;;16235:4;16222:18;;;16173:21;-1:-1:-1;;;;;16256:32:49;;16253:52;;;16301:1;16298;16291:12;16253:52;16354:8;16338:14;16334:29;16325:7;16321:43;16318:63;;;16377:1;16374;16367:12;16318:63;16402:51;16448:4;16438:8;16429:7;16402:51;:::i;:::-;16488:4;16513:14;;;;16394:59;;-1:-1:-1;16476:17:49;;;;;-1:-1:-1;;15851:1:49;15844:9;15815:722;;;-1:-1:-1;16553:4:49;;15532:1031;-1:-1:-1;;;;;;15532:1031:49:o;16568:1099::-;17026:3;17015:9;17008:22;16989:4;17053:63;17111:3;17100:9;17096:19;17088:6;17080;17053:63;:::i;:::-;-1:-1:-1;;;;;17152:32:49;;;17147:2;17132:18;;17125:60;17216:2;17201:18;;17194:34;;;17264:32;;17259:2;17244:18;;17237:60;17334:22;;;17328:3;17313:19;;17306:51;17374:68;17338:6;17427;17419;17374:68;:::i;:::-;17486:14;;17479:22;17473:3;17458:19;;17451:51;-1:-1:-1;;;;;;;17539:32:49;;;;17533:3;17518:19;;17511:61;17603:3;17588:19;;17581:35;;;;17647:3;17632:19;;;17625:36;17366:76;16568:1099;-1:-1:-1;;;;;;;16568:1099:49:o;17672:953::-;18073:3;18062:9;18055:22;18036:4;18100:63;18158:3;18147:9;18143:19;18135:6;18127;18100:63;:::i;:::-;-1:-1:-1;;;;;18199:32:49;;;18194:2;18179:18;;18172:60;18263:2;18248:18;;18241:34;;;18311:32;;18306:2;18291:18;;18284:60;18381:22;;;18375:3;18360:19;;18353:51;18421:68;18385:6;18474;18466;18421:68;:::i;:::-;18533:14;;18526:22;18520:3;18505:19;;18498:51;-1:-1:-1;;;;;;;18586:32:49;;;;18580:3;18565:19;;;18558:61;18413:76;17672:953;-1:-1:-1;;;;;;;17672:953:49:o;18630:175::-;18667:3;18711:4;18704:5;18700:16;18740:4;18731:7;18728:17;18725:43;;18748:18;;:::i;:::-;18797:1;18784:15;;18630:175;-1:-1:-1;;18630:175:49:o;19362:127::-;19423:10;19418:3;19414:20;19411:1;19404:31;19454:4;19451:1;19444:15;19478:4;19475:1;19468:15;20131:386;20368:6;20357:9;20350:25;20411:2;20406;20395:9;20391:18;20384:30;20331:4;20431:80;20507:2;20496:9;20492:18;20484:6;20476;20431:80;:::i;:::-;20423:88;20131:386;-1:-1:-1;;;;;20131:386:49:o;20522:1514::-;20626:6;20679:2;20667:9;20658:7;20654:23;20650:32;20647:52;;;20695:1;20692;20685:12;20647:52;20728:9;20722:16;-1:-1:-1;;;;;20753:6:49;20750:30;20747:50;;;20793:1;20790;20783:12;20747:50;20816:22;;20869:4;20861:13;;20857:27;-1:-1:-1;20847:55:49;;20898:1;20895;20888:12;20847:55;20931:2;20925:9;-1:-1:-1;;;;;20949:6:49;20946:30;20943:56;;;20979:18;;:::i;:::-;21025:6;21022:1;21018:14;21052:28;21076:2;21072;21068:11;21052:28;:::i;:::-;21114:19;;;21158:2;21188:11;;;21184:20;;;21149:12;;;;21216:19;;;21213:39;;;21248:1;21245;21238:12;21213:39;21280:2;21276;21272:11;21261:22;;21292:714;21308:6;21303:3;21300:15;21292:714;;;21387:3;21381:10;-1:-1:-1;;;;;21410:11:49;21407:35;21404:55;;;21455:1;21452;21445:12;21404:55;21482:20;;21537:2;21529:11;;21525:25;-1:-1:-1;21515:53:49;;21564:1;21561;21554:12;21515:53;21611:2;21607;21603:11;21597:18;21643:55;21659:38;21688:8;21659:38;:::i;21643:55::-;21711:25;;;21755:35;21763:17;;;21755:35;21752:48;-1:-1:-1;21749:68:49;;;21813:1;21810;21803:12;21749:68;21867:8;21862:2;21858;21854:11;21849:2;21840:7;21836:16;21830:46;21929:1;21924:2;21913:8;21904:7;21900:22;21896:31;21889:42;21956:7;21951:3;21944:20;;;;21993:2;21988:3;21984:12;21977:19;;21334:2;21329:3;21325:12;21318:19;;21292:714;;;22025:5;20522:1514;-1:-1:-1;;;;;;;20522:1514:49:o;22041:212::-;22083:3;22121:5;22115:12;22165:6;22158:4;22151:5;22147:16;22142:3;22136:36;22227:1;22191:16;;22216:13;;;-1:-1:-1;22191:16:49;;22041:212;-1:-1:-1;22041:212:49:o;22384:1171::-;22560:3;22588:30;22614:3;22606:6;22588:30;:::i;:::-;22665:13;;22638:1;;22725;22721:17;;;;22773;;;22799:61;;22853:4;22845:6;22841:17;22831:27;;22799:61;22906:2;22898:6;22895:14;22875:18;22872:38;22869:161;;22952:10;22947:3;22943:20;22940:1;22933:31;22987:4;22984:1;22977:15;23015:4;23012:1;23005:15;22869:161;23046:18;23073:131;;;;23218:1;23213:317;;;;23039:491;;23073:131;-1:-1:-1;;23105:24:49;;23094:36;;23177:14;;23170:22;23158:35;;23150:44;;;-1:-1:-1;23073:131:49;;23213:317;22331:1;22324:14;;;22368:4;22355:18;;23308:1;23322:163;23336:6;23333:1;23330:13;23322:163;;;23413:14;;23401:10;;;23394:34;23469:1;23456:15;;;;23358:2;23351:10;23322:163;;;23326:3;;23513:6;23509:2;23505:15;23498:22;;23039:491;-1:-1:-1;23546:3:49;;22384:1171;-1:-1:-1;;;;;;;;22384:1171:49:o;23560:524::-;-1:-1:-1;;;;;23793:32:49;;;23775:51;;23862:32;;;23857:2;23842:18;;23835:60;23931:32;;23926:2;23911:18;;23904:60;24000:3;23995:2;23980:18;;23973:31;;;-1:-1:-1;;24021:57:49;;24058:19;;24050:6;24021:57;:::i;24278:190::-;24407:3;24432:30;24458:3;24450:6;24432:30;:::i;24473:127::-;24534:10;24529:3;24525:20;24522:1;24515:31;24565:4;24562:1;24555:15;24589:4;24586:1;24579:15
Swarm Source
ipfs://da0ca7e1edbb9f75fec4d6f45675905d8a439e3bd51fd05cdba95dfb408b15c7
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ 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.