POL Price: $0.218431 (-0.71%)
Gas: 31.2 GWei
 

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Register673673782025-01-31 12:06:4181 days ago1738325201IN
0xFB07B082...92D0CB242
0.02 POL0.0098658639.44910276
Register653542542024-12-11 14:06:43132 days ago1733926003IN
0xFB07B082...92D0CB242
0.02 POL0.02744205110.97833597
Register645679422024-11-21 20:30:03152 days ago1732221003IN
0xFB07B082...92D0CB242
0.02 POL0.0065067830.01035809
Register642378412024-11-13 14:19:14160 days ago1731507554IN
0xFB07B082...92D0CB242
0.02 POL0.05456196219.8191247
Register642225352024-11-13 5:07:30161 days ago1731474450IN
0xFB07B082...92D0CB242
0.02 POL0.02830026130.52542913
Register642225172024-11-13 5:06:52161 days ago1731474412IN
0xFB07B082...92D0CB242
0.02 POL0.03286294152.22855281
Register642224832024-11-13 5:05:38161 days ago1731474338IN
0xFB07B082...92D0CB242
5.40855742 POL0.03824454187.19611801
Register642224512024-11-13 5:04:30161 days ago1731474270IN
0xFB07B082...92D0CB242
0.02 POL0.04125739191.11349558
Register642224272024-11-13 5:03:38161 days ago1731474218IN
0xFB07B082...92D0CB242
0.02 POL0.04640022185.54225931
Register640073872024-11-07 20:21:15166 days ago1731010875IN
0xFB07B082...92D0CB242
0.02 POL0.0075027330.00000007
Register639250022024-11-05 18:58:34168 days ago1730833114IN
0xFB07B082...92D0CB242
0.02 POL0.0072845233.8909472
Register639249822024-11-05 18:57:52168 days ago1730833072IN
0xFB07B082...92D0CB242
0.02 POL0.0074022234.58773468
Register639248932024-11-05 18:54:42168 days ago1730832882IN
0xFB07B082...92D0CB242
0.02 POL0.007837336.30414429
Register639248252024-11-05 18:52:18168 days ago1730832738IN
0xFB07B082...92D0CB242
0.02 POL0.0072408333.98462293
Register639247742024-11-05 18:50:30168 days ago1730832630IN
0xFB07B082...92D0CB242
0.02 POL0.0077158935.74175386
Register639247122024-11-05 18:48:18168 days ago1730832498IN
0xFB07B082...92D0CB242
0.02 POL0.0077097335.8692639
Register639246542024-11-05 18:46:12168 days ago1730832372IN
0xFB07B082...92D0CB242
0.02 POL0.0083567233.66917365
Register639003192024-11-05 4:21:16169 days ago1730780476IN
0xFB07B082...92D0CB242
0.02 POL0.0088878235.80899584
Register638430602024-11-03 17:51:02170 days ago1730656262IN
0xFB07B082...92D0CB242
0.02 POL0.0065327130.00000003
Register638386012024-11-03 15:11:57170 days ago1730646717IN
0xFB07B082...92D0CB242
0.02 POL0.0204919596.17836092
Register638384612024-11-03 15:06:59170 days ago1730646419IN
0xFB07B082...92D0CB242
0.02 POL0.0204383695.50591557
Register638384442024-11-03 15:06:23170 days ago1730646383IN
0xFB07B082...92D0CB242
0.02 POL0.02324733109.11068042
Register638384222024-11-03 15:05:37170 days ago1730646337IN
0xFB07B082...92D0CB242
0.02 POL0.02318388108.81285386
Register638383992024-11-03 15:04:47170 days ago1730646287IN
0xFB07B082...92D0CB242
0.02 POL0.01522461.57032124
Register638382742024-11-03 15:00:23170 days ago1730646023IN
0xFB07B082...92D0CB242
0.02 POL0.0121629956.83616892
View all transactions

Latest 25 internal transactions (View All)

Parent Transaction Hash Block From To
673673782025-01-31 12:06:4181 days ago1738325201
0xFB07B082...92D0CB242
0.02 POL
653542542024-12-11 14:06:43132 days ago1733926003
0xFB07B082...92D0CB242
0.02 POL
645679422024-11-21 20:30:03152 days ago1732221003
0xFB07B082...92D0CB242
0.02 POL
642378412024-11-13 14:19:14160 days ago1731507554
0xFB07B082...92D0CB242
0.02 POL
642225352024-11-13 5:07:30161 days ago1731474450
0xFB07B082...92D0CB242
0.02 POL
642225172024-11-13 5:06:52161 days ago1731474412
0xFB07B082...92D0CB242
0.02 POL
642224832024-11-13 5:05:38161 days ago1731474338
0xFB07B082...92D0CB242
0.02874249 POL
642224512024-11-13 5:04:30161 days ago1731474270
0xFB07B082...92D0CB242
0.02 POL
642224272024-11-13 5:03:38161 days ago1731474218
0xFB07B082...92D0CB242
0.02 POL
640073872024-11-07 20:21:15166 days ago1731010875
0xFB07B082...92D0CB242
0.02 POL
639250022024-11-05 18:58:34168 days ago1730833114
0xFB07B082...92D0CB242
0.02 POL
639249822024-11-05 18:57:52168 days ago1730833072
0xFB07B082...92D0CB242
0.02 POL
639248932024-11-05 18:54:42168 days ago1730832882
0xFB07B082...92D0CB242
0.02 POL
639248252024-11-05 18:52:18168 days ago1730832738
0xFB07B082...92D0CB242
0.02 POL
639247742024-11-05 18:50:30168 days ago1730832630
0xFB07B082...92D0CB242
0.02 POL
639247122024-11-05 18:48:18168 days ago1730832498
0xFB07B082...92D0CB242
0.02 POL
639246542024-11-05 18:46:12168 days ago1730832372
0xFB07B082...92D0CB242
0.02 POL
639003192024-11-05 4:21:16169 days ago1730780476
0xFB07B082...92D0CB242
0.02 POL
638430602024-11-03 17:51:02170 days ago1730656262
0xFB07B082...92D0CB242
0.02 POL
638386012024-11-03 15:11:57170 days ago1730646717
0xFB07B082...92D0CB242
0.02 POL
638384612024-11-03 15:06:59170 days ago1730646419
0xFB07B082...92D0CB242
0.02 POL
638384442024-11-03 15:06:23170 days ago1730646383
0xFB07B082...92D0CB242
0.02 POL
638384222024-11-03 15:05:37170 days ago1730646337
0xFB07B082...92D0CB242
0.02 POL
638383992024-11-03 15:04:47170 days ago1730646287
0xFB07B082...92D0CB242
0.02 POL
638382742024-11-03 15:00:23170 days ago1730646023
0xFB07B082...92D0CB242
0.02 POL
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
NFTRegistrar

Compiler Version
v0.8.20+commit.a1b79de6

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion
File 1 of 12 : NFTRegistrar.sol
/// @author premm.eth (Unruggable)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

import {StringUtils} from "./utils/StringUtils.sol";
import {Address} from "@openzeppelin/contracts/utils/Address.sol";
import {BytesUtilsSub} from "./utils/BytesUtilsSub.sol";
import {INFTRegistry} from "./INFTRegistry.sol";
import {Balances} from "./Balances.sol";
import {IAggregatorInterface} from "./IAggregatorInterface.sol";
import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol";

error CommitmentTooNew(bytes32 commitment);
error CommitmentTooOld(bytes32 commitment);
error DurationTooShort(uint256 duration);
error ResolverRequiredWhenDataSupplied();
error UnexpiredCommitmentExists(bytes32 commitment);
error InsufficientValue();
error UnauthorizedAddress(uint256 tokenId);
error MaxCommitmentAgeTooLow();
error MaxCommitmentAgeTooHigh();
error WrongNumberOfChars(string label);
error NoPricingData();
error CannotSetNewCharLengthAmounts();
error InvalidDuration(uint256 duration);
error LabelTooShort();
error LabelTooLong();

error ERC721NonexistentToken(uint256 tokenId);

contract NFTRegistrar is Balances /* AccessControl */ {
    using StringUtils for string;
    using Address for address payable;
    using BytesUtilsSub for bytes;

    uint256 private constant MAX_EXPIRY = type(uint256).max;
    uint256 public immutable minCommitmentAge;
    uint256 public immutable maxCommitmentAge;

    // target registry
    INFTRegistry public immutable targetRegistry;

    // Chainlink oracle address
    IAggregatorInterface public usdOracle;

    // The pricing and character requirements for registrations.
    uint256 public minRegistrationDuration;
    uint256 public maxRegistrationDuration;
    uint16 public minChars;
    uint16 public maxChars;
    uint256[] public charAmounts;

    mapping(bytes32 => uint256) public commitments;

    mapping(address wallet => uint256) public freeRegistrations;

    // the maximum number of registrstions that can be made for free.
    uint256 public maxFreeRegistrations;

    constructor(
        INFTRegistry _registry,
        uint256 _minCommitmentAge,
        uint256 _maxCommitmentAge,
        IAggregatorInterface _usdOracle
    ) {
        targetRegistry = _registry;

        if (_maxCommitmentAge <= _minCommitmentAge) {
            revert MaxCommitmentAgeTooLow();
        }

        minCommitmentAge = _minCommitmentAge;
        maxCommitmentAge = _maxCommitmentAge;

        // Set the oracle address.
        usdOracle = _usdOracle;

        // Grant the contract deployer the default admin role and the admin role
        _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
        _grantRole(ADMIN_ROLE, msg.sender);
    }

    // a setter function for the maxFreeRegistrations
    function setMaxFreeRegistrations(
        uint256 _maxFreeRegistrations
    ) public onlyRole(ADMIN_ROLE) {
        maxFreeRegistrations = _maxFreeRegistrations;
    }

    // a way to update the balance of free registrations for a batch of addresses
    function updateFreeRegistrations(
        address[] calldata addresses,
        uint256[] calldata amounts
    ) public onlyRole(ADMIN_ROLE) {
        require(
            addresses.length == amounts.length,
            "Arrays must be the same length"
        );
        for (uint256 i = 0; i < addresses.length; i++) {
            freeRegistrations[addresses[i]] = amounts[i];
        }
    }

    /**
     * @dev Checks if a given tokenId is available for registration.
     * @param tokenId The tokenId to check.
     * @return available True if the tokenId is available, false otherwise.
     */
    function available(uint256 tokenId) external view returns (bool) {
        try targetRegistry.ownerOf(tokenId) returns (address) {
            // If ownerOf doesn't revert, the token exists, so it is not available
            return false;
        } catch (bytes memory reason) {
            // Catch the specific custom error using error signature comparison
            if (
                keccak256(reason) ==
                keccak256(
                    abi.encodeWithSelector(
                        ERC721NonexistentToken.selector,
                        tokenId
                    )
                )
            ) {
                // Token does not exist (minting has not happened), it is available
                return true;
            } else {
                // Re-throw if it's another type of error
                revert(string(reason));
            }
        }
    }

    // a register function that uses mint to register a label
    function register(
        string memory label,
        address owner,
        uint256 duration
    ) public payable {
        // Check to make sure the duration is between the min and max.
        if (
            duration < minRegistrationDuration ||
            duration > maxRegistrationDuration
        ) {
            revert InvalidDuration(duration);
        }

        // Check to make sure the label is a valid length.
        if (!validLength(label)) {
            revert WrongNumberOfChars(label);
        }

        // Get the price for the duration.
        (uint256 price, ) = rentPrice(label, duration);

        // If the price is zero increment the free registration count.
        if (price == 0) {
            // If either the msg.sender or the owner's balance of free names
            // are greater than maxFreeRegistrations then revert.
            if (
                freeRegistrations[msg.sender] >= maxFreeRegistrations ||
                freeRegistrations[owner] >= maxFreeRegistrations
            ) {
                revert("Max free registrations exceeded");
            }

            // If the msg.sender and the owner are the same than just update the msg.sender's balance.
            if (msg.sender == owner) {
                freeRegistrations[msg.sender] += 1;
            } else {
                // If the msg.sender and the owner are different than update both balances.
                freeRegistrations[msg.sender] += 1;
                freeRegistrations[owner] += 1;
            }
        }

        // Check to make sure the caller sent enough Eth.
        if (msg.value < price) {
            revert InsufficientValue();
        }

        // use setLabel to register the label
        targetRegistry.register(
            label,
            owner,
            uint256(block.timestamp + duration)
        );

        // Because the oracle can return a slightly different value then what was estimated
        // we can overestimate the price and then return any difference.
        if (msg.value > price) {
            payable(msg.sender).sendValue(msg.value - price);
        }
    }

    // renew function that uses setExpiry to renew a label
    function renew(string memory label, uint256 duration) public payable {
        // make a tokenId from the label
        uint256 tokenId = uint256(keccak256(bytes(label)));
        // make a labelhash from the label
        bytes32 labelhash = keccak256(abi.encodePacked(label));

        // get the expiry data for tokenId
        uint256 expiry = targetRegistry.getExpiry(labelhash);

        // make sure only the owner of the label is the caller.
        if (msg.sender != targetRegistry.ownerOf(tokenId)) {
            revert UnauthorizedAddress(tokenId);
        }

        // Check to make sure the duration is between the min and max.
        if (
            duration < minRegistrationDuration ||
            duration > maxRegistrationDuration
        ) {
            revert InvalidDuration(duration);
        }

        // Get the price for the duration.
        (uint256 price, ) = rentPrice(label, duration);

        // Check to make sure the caller sent enough Eth.
        if (msg.value < price) {
            revert InsufficientValue();
        }

        // use setExpiry to renew the label
        targetRegistry.setExpiry(labelhash, uint64(expiry + duration));

        // If more Eth was sent than the price then return the difference.
        if (msg.value > price) {
            payable(msg.sender).sendValue(msg.value - price);
        }
    }

    /**
     * @notice Gets the total cost of rent in wei, from the unitPrice, i.e. USD, and duration.
     * @param duration The amount of time the label will be rented for/extended in years.
     * @return weiPrice The rent price for the duration in Wei
     * @return usdPrice The rent price for the duration in USD
     */

    function rentPrice(
        string memory label,
        uint256 duration
    ) public view returns (uint256 weiPrice, uint256 usdPrice) {
        uint256 labelLength = label.strlen();

        // Get the length of the charAmounts array.
        uint256 charAmountsLength = charAmounts.length;

        // The price of the length of the label in USD/sec. (with 18 digits of precision).
        uint256 unitPrice;

        if (charAmountsLength > 0) {
            // Check to make sure the price for labelLength exists.
            // If not use the default price charAmounts[0].
            if (labelLength < charAmountsLength) {
                // Get the unit price, i.e. the price in USD/sec, for the length of
                // the label. If there is not a price set then use the defualt amount.
                unitPrice = charAmounts[labelLength];

                // If the unit price is 0 then use the default amount.
                if (unitPrice == 0) {
                    unitPrice = charAmounts[0];
                }
            } else {
                // Get the unit price, i.e. the price in USD/sec using the defualt amount.
                unitPrice = charAmounts[0];
            }
        } else {
            //If there is no pricing data, return 0, i.e. free.
            return (0, 0);
        }

        // Convert the unit price from USD to Wei.
        return (_usdToWei(unitPrice * duration), unitPrice * duration);
    }

    /**
     * @notice checkes to see if the length of the label is greater than the min. and less than the max.
     * @param label Label as a string, e.g. "vault" or vault.vitalik.eth.
     */

    function validLength(string memory label) internal view returns (bool) {
        // The label is valid if the number of characters of the label is greater than the
        // minimum and the less than the maximum or the maximum is 0, return true.
        if (label.strlen() >= minChars) {
            // If the maximum characters is set then check to make sure the label is
            // shorter or equal to it.
            if (maxChars != 0 && label.strlen() > maxChars) {
                return false;
            } else {
                return true;
            }
        } else {
            return false;
        }
    }

    // create a function to set the usd oracle address
    function setUSDOracle(address _oracle) public onlyRole(ADMIN_ROLE) {
        usdOracle = IAggregatorInterface(_oracle);
    }

    /**
     * @notice Set the pricing for subnames of the parent name.
     * @param _minRegistrationDuration The minimum duration a name can be registered for.
     * @param _maxRegistrationDuration The maximum duration a name can be registered for.
     * @param _minChars The minimum length a name can be.
     * @param _maxChars The maximum length a name can be.
     */

    function setParams(
        uint256 _minRegistrationDuration,
        uint256 _maxRegistrationDuration,
        uint16 _minChars,
        uint16 _maxChars
    ) public onlyRole(ADMIN_ROLE) {
        // Set the pricing for subnames of the parent node.
        minRegistrationDuration = _minRegistrationDuration;
        maxRegistrationDuration = _maxRegistrationDuration;
        minChars = _minChars;
        maxChars = _maxChars;
    }

    /**
     * @notice Set the pricing for subname lengths.
     * @param _charAmounts An array of amounst for each characer length.
     */

    function setPricingForAllLengths(
        uint256[] calldata _charAmounts
    ) public onlyRole(ADMIN_ROLE) {
        // Clear the old dynamic array out
        delete charAmounts;

        // Set the pricing for subnames of the parent node.
        charAmounts = _charAmounts;
    }

    /**
     * @notice Get the price for a single character length, e.g. three characters.
     * @param charLength The character length, e.g. 3 would be for three characters. Use 0 for the default amount.
     */
    function getPriceDataForLength(
        uint16 charLength
    ) public view returns (uint256) {
        return charAmounts[charLength];
    }

    /**
     * @notice Set a price for a single character length, e.g. three characters.
     * @param charLength The character length, e.g. 3 would be for three characters. Use 0 for the default amount.
     * @param charAmount The amount in USD/year for a character count, e.g. amount for three characters.
     */
    function updatePriceForCharLength(
        uint16 charLength,
        uint256 charAmount
    ) public onlyRole(ADMIN_ROLE) {
        // Check that the charLength is not greater than the last index of the charAmounts array.
        if (charLength > charAmounts.length - 1) {
            revert CannotSetNewCharLengthAmounts();
        }
        charAmounts[charLength] = charAmount;
    }

    /**
     * @notice Adds a price for the next character length, e.g. three characters.
     * @param charAmount The amount in USD/sec. (with 18 digits of precision)
     * for a character count, e.g. amount for three characters.
     */
    function addNextPriceForCharLength(
        uint256 charAmount
    ) public onlyRole(ADMIN_ROLE) {
        charAmounts.push(charAmount);
    }

    /**
     * @notice Get the last length for a character length that has a price (can be 0), e.g. three characters.
     * @return The length of the last character length that was set.
     */
    function getLastCharIndex() public view returns (uint256) {
        return charAmounts.length - 1;
    }

    /* Internal functions */

    /**
     * @dev Converts USD to Wei.
     * @param amount The amount of USD to be converted to Wei.
     * @return The amount of Wei.
     */
    function _usdToWei(uint256 amount) internal view returns (uint256) {
        // Get the price of ETH in USD (with 8 digits of precision) from the oracle.
        uint256 ethPrice = uint256(usdOracle.latestAnswer());

        // Convert the amount of USD (with 18 digits of precision) to Wei.
        return (amount * 1e8) / ethPrice;
    }

    function _burnCommitment(bytes32 commitment) internal {
        // Require an old enough commitment.
        if (commitments[commitment] + minCommitmentAge > block.timestamp) {
            revert CommitmentTooNew(commitment);
        }

        // If the commitment is too old, or the label is registered, stop
        if (commitments[commitment] + maxCommitmentAge <= block.timestamp) {
            revert CommitmentTooOld(commitment);
        }

        delete (commitments[commitment]);
    }
}

File 2 of 12 : StringUtils.sol
pragma solidity >=0.8.4;

library StringUtils {
    /**
     * @dev Returns the length of a given string
     *
     * @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) {
        uint256 len;
        uint256 i = 0;
        uint256 bytelength = bytes(s).length;
        for (len = 0; i < bytelength; len++) {
            bytes1 b = bytes(s)[i];
            if (b < 0x80) {
                i += 1;
            } else if (b < 0xE0) {
                i += 2;
            } else if (b < 0xF0) {
                i += 3;
            } else if (b < 0xF8) {
                i += 4;
            } else if (b < 0xFC) {
                i += 5;
            } else {
                i += 6;
            }
        }
        return len;
    }
}

File 3 of 12 : Address.sol
// 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();
        }
    }
}

File 4 of 12 : BytesUtilsSub.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

library BytesUtilsSub {
    /*
     * @dev Returns the keccak-256 hash of a byte range.
     * @param self The byte string to hash.
     * @param offset The position to start hashing at.
     * @param len The number of bytes to hash.
     * @return The hash of the byte range.
     */
    function keccak(
        bytes memory self,
        uint256 offset,
        uint256 len
    ) internal pure returns (bytes32 ret) {
        require(offset + len <= self.length);
        assembly {
            ret := keccak256(add(add(self, 32), offset), len)
        }
    }

    /**
     * @dev Returns the ENS namehash of a DNS-encoded name.
     * @param self The DNS-encoded name to hash.
     * @param offset The offset at which to start hashing.
     * @return The namehash of the name.
     */
    function namehash(
        bytes memory self,
        uint256 offset
    ) internal pure returns (bytes32) {
        (bytes32 labelhash, uint256 newOffset) = readLabel(self, offset);
        if (labelhash == bytes32(0)) {
            require(offset == self.length - 1, "namehash: Junk at end of name");
            return bytes32(0);
        }
        return
            keccak256(abi.encodePacked(namehash(self, newOffset), labelhash));
    }

    /**
     * @dev Returns the keccak-256 hash of a DNS-encoded label, and the offset to the start of the next label.
     * @param self The byte string to read a label from.
     * @param idx The index to read a label at.
     * @return labelhash The hash of the label at the specified index, or 0 if it is the last label.
     * @return newIdx The index of the start of the next label.
     */
    function readLabel(
        bytes memory self,
        uint256 idx
    ) internal pure returns (bytes32 labelhash, uint256 newIdx) {
        require(idx < self.length, "readLabel: Index out of bounds");
        uint256 len = uint256(uint8(self[idx]));
        if (len > 0) {
            labelhash = keccak(self, idx + 1, len);
        } else {
            labelhash = bytes32(0);
        }
        newIdx = idx + len + 1;
    }

    /**
     * @dev This function takes a bytes input which represents the DNS name and
     * returns the first label of a domain name in DNS format.
     * @param domain The domain in DNS format wherein the length precedes each label
     * and is terminted with a 0x0 byte, e.g. "cb.id" => [0x02,0x63,0x62,0x02,0x69,0x64,0x00].
     * @return string memory the first label.
     */

    function getFirstLabel(
        bytes memory domain
    ) internal pure returns (string memory, uint256) {
        // Get the first byte of the domain which represents the length of the first label
        uint256 labelLength = uint256(uint8(domain[0]));

        // Check to make sure the label length is less than the domain length and greater than zero.
        require(labelLength < domain.length && labelLength > 0);

        // Create a new byte array to hold the first label
        bytes memory firstLabel = new bytes(labelLength);

        // Iterate through the domain bytes to copy the first label to the new byte array
        // skipping the first byte which represents the length of the first label.
        for (uint256 i = 0; i < labelLength; ++i) {
            firstLabel[i] = domain[i + 1];
        }

        // Convert the first label to string and return, with the length of the first label.
        return (string(firstLabel), labelLength);
    }

    /**
     * @dev This function takes a bytes input which represents the DNS name and
     * returns the TLD (last label) of a domain name. A domain can have a maximum of 10 labels.
     * @param domain bytes memory.
     * @return string memory the TLD.
     */

    function getTLD(bytes memory domain) internal pure returns (string memory) {
        // Variable used to keep track of the level count.

        uint levels = 0;
        // Variable used to keep track of the index of each length byte.

        // Iterate through the domain bytes.
        for (uint i = 0; i < domain.length; i++) {
            // If level count exceed 10, break the loop.
            if (levels > 10) {
                break;
            }

            // Get the label length from the current byte.
            uint labelLength = uint(uint8(domain[i]));

            // Check to make sure we have found the terminal byte and it is equal to zero.
            if (
                i + labelLength + 2 == domain.length &&
                domain[labelLength + i + 1] == 0
            ) {
                // Create a new byte array to hold the TLD.
                bytes memory lastLabel = new bytes(labelLength);

                // Copy the TLD from the domain array to the new byte array.
                for (uint j = 0; j < labelLength; j++) {
                    lastLabel[j] = domain[i + 1 + j];
                }

                // Convert the TLD to string and return.
                return string(lastLabel);
            }

            // Move to the next label
            i += labelLength;

            // Increment the level count.
            levels++;
        }

        // Revert if TLD not found.
        revert("TLD not found");
    }

    //"\x03123\x03eth\x00";

    function replaceTLD(
        bytes memory domain,
        bytes memory newTld
    ) internal pure returns (string memory) {
        // Variable used to keep track of the level count.

        uint levels = 0;
        // Variable used to keep track of the index of each length byte.

        uint lastLabelLength = 0;

        // Iterate through the domain bytes.
        for (uint i = 0; i < domain.length; ) {
            // If level count exceed 10, break the loop.
            if (levels > 10) {
                break;
            }

            // Get the label length from the current byte.
            uint labelLength = uint(uint8(domain[i]));

            i += labelLength + 1;

            if (labelLength != 0) {
                lastLabelLength = labelLength;
                levels++;

                continue;
            }
        }

        if (levels <= 10) {
            uint newTldLength = newTld.length;

            bytes memory newName = new bytes(
                domain.length - lastLabelLength + newTldLength - 2
            );

            uint newNameLength = 0;

            for (uint i = 0; i < domain.length - (lastLabelLength + 2); i++) {
                newName[i] = domain[i];
                newNameLength++;
            }

            for (uint j = 0; j < newTldLength; j++) {
                newName[j + newNameLength] = newTld[j];
            }

            return string(newName);
        }

        // Revert if TLD not found.
        revert("TLD not found");
    }
}

File 5 of 12 : INFTRegistry.sol
/// @author darianb.eth
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

interface INFTRegistry {
    // Errors
    error Unauthorized();
    error TokenExpired(bytes32 labelhash, uint256 expiry);

    // Events
    event Registered(string label, address owner);
    event TextChanged(bytes32 indexed labelhash, string key, string value);
    event AddrChanged(bytes32 indexed labelhash, uint256 coinType, bytes value);
    event ContenthashChanged(bytes32 indexed labelhash, bytes value);

    // Structs
    struct Text {
        string key;
        string value;
    }
    struct Addr {
        uint256 coinType;
        bytes value;
    }

    // ERC721 methods
    function ownerOf(uint256 tokenId) external view returns (address);

    // AccessControl methods
    function supportsInterface(bytes4 interfaceId) external view returns (bool);

    // NFTRegistry specific methods
    function totalSupply() external view returns (uint256);
    function baseUri() external view returns (string memory);
    function addRegistrar(address registrar) external;
    function removeRegistrar(address registrar) external;
    function register(
        string calldata label,
        address owner,
        uint256 expiry
    ) external;
    function addr(bytes32 labelhash) external view returns (address);
    function addr(
        bytes32 labelhash,
        uint256 cointype
    ) external view returns (bytes memory);
    function text(
        bytes32 labelhash,
        string calldata key
    ) external view returns (string memory);
    function contenthash(
        bytes32 labelhash
    ) external view returns (bytes memory);
    function getExpiry(bytes32 labelhash) external view returns (uint64);
    function available(uint256 tokenId) external view returns (bool);
    function labelFor(bytes32 labelhash) external view returns (string memory);
    function setBaseURI(string memory _baseUri) external;
    function setAddr(
        bytes32 labelhash,
        uint256 coinType,
        bytes calldata value
    ) external;
    function setText(
        bytes32 labelhash,
        string calldata key,
        string calldata value
    ) external;
    function setContenthash(bytes32 labelhash, bytes calldata value) external;
    function setExpiry(bytes32 labelhash, uint64 expiry) external;
    function setRecords(
        bytes32 labelhash,
        Text[] calldata texts,
        Addr[] calldata addrs,
        bytes[] calldata chash
    ) external;
}

File 6 of 12 : Balances.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol";
import {Address} from "@openzeppelin/contracts/utils/Address.sol";

abstract contract Balances is AccessControl {
    using Address for address payable;

    event AddressWithdrew(address indexed _address, uint256 indexed amount);

    bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");

    /**
     * @notice A function to allow referrers, name owners, or the contract owner to withdraw.
     */

    function withdraw(uint256 amount) public onlyRole(ADMIN_ROLE) {
        //get the address of the sender
        address payable sender = payable(msg.sender);

        emit AddressWithdrew(sender, amount);

        // Send the amount to the contract owner's address.
        sender.sendValue(amount);
    }
}

File 7 of 12 : IAggregatorInterface.sol
//SPDX-License-Identifier: MIT
pragma solidity ~0.8.17;

// Chainlink oracle interface
interface IAggregatorInterface {
    function latestAnswer() external view returns (int256);
}

File 8 of 12 : AccessControl.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)

pragma solidity ^0.8.20;

import {IAccessControl} from "./IAccessControl.sol";
import {Context} from "../utils/Context.sol";
import {ERC165} from "../utils/introspection/ERC165.sol";

/**
 * @dev Contract module that allows children to implement role-based access
 * control mechanisms. This is a lightweight version that doesn't allow enumerating role
 * members except through off-chain means by accessing the contract event logs. Some
 * applications may benefit from on-chain enumerability, for those cases see
 * {AccessControlEnumerable}.
 *
 * Roles are referred to by their `bytes32` identifier. These should be exposed
 * in the external API and be unique. The best way to achieve this is by
 * using `public constant` hash digests:
 *
 * ```solidity
 * bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
 * ```
 *
 * Roles can be used to represent a set of permissions. To restrict access to a
 * function call, use {hasRole}:
 *
 * ```solidity
 * function foo() public {
 *     require(hasRole(MY_ROLE, msg.sender));
 *     ...
 * }
 * ```
 *
 * Roles can be granted and revoked dynamically via the {grantRole} and
 * {revokeRole} functions. Each role has an associated admin role, and only
 * accounts that have a role's admin role can call {grantRole} and {revokeRole}.
 *
 * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
 * that only accounts with this role will be able to grant or revoke other
 * roles. More complex role relationships can be created by using
 * {_setRoleAdmin}.
 *
 * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
 * grant and revoke this role. Extra precautions should be taken to secure
 * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}
 * to enforce additional security measures for this role.
 */
abstract contract AccessControl is Context, IAccessControl, ERC165 {
    struct RoleData {
        mapping(address account => bool) hasRole;
        bytes32 adminRole;
    }

    mapping(bytes32 role => RoleData) private _roles;

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

    /**
     * @dev Modifier that checks that an account has a specific role. Reverts
     * with an {AccessControlUnauthorizedAccount} error including the required role.
     */
    modifier onlyRole(bytes32 role) {
        _checkRole(role);
        _;
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
    }

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) public view virtual returns (bool) {
        return _roles[role].hasRole[account];
    }

    /**
     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`
     * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.
     */
    function _checkRole(bytes32 role) internal view virtual {
        _checkRole(role, _msgSender());
    }

    /**
     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`
     * is missing `role`.
     */
    function _checkRole(bytes32 role, address account) internal view virtual {
        if (!hasRole(role, account)) {
            revert AccessControlUnauthorizedAccount(account, role);
        }
    }

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {
        return _roles[role].adminRole;
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     *
     * May emit a {RoleGranted} event.
     */
    function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
        _grantRole(role, account);
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     *
     * May emit a {RoleRevoked} event.
     */
    function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
        _revokeRole(role, account);
    }

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been revoked `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `callerConfirmation`.
     *
     * May emit a {RoleRevoked} event.
     */
    function renounceRole(bytes32 role, address callerConfirmation) public virtual {
        if (callerConfirmation != _msgSender()) {
            revert AccessControlBadConfirmation();
        }

        _revokeRole(role, callerConfirmation);
    }

    /**
     * @dev Sets `adminRole` as ``role``'s admin role.
     *
     * Emits a {RoleAdminChanged} event.
     */
    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
        bytes32 previousAdminRole = getRoleAdmin(role);
        _roles[role].adminRole = adminRole;
        emit RoleAdminChanged(role, previousAdminRole, adminRole);
    }

    /**
     * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleGranted} event.
     */
    function _grantRole(bytes32 role, address account) internal virtual returns (bool) {
        if (!hasRole(role, account)) {
            _roles[role].hasRole[account] = true;
            emit RoleGranted(role, account, _msgSender());
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleRevoked} event.
     */
    function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {
        if (hasRole(role, account)) {
            _roles[role].hasRole[account] = false;
            emit RoleRevoked(role, account, _msgSender());
            return true;
        } else {
            return false;
        }
    }
}

File 9 of 12 : IAccessControl.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)

pragma solidity ^0.8.20;

/**
 * @dev External interface of AccessControl declared to support ERC165 detection.
 */
interface IAccessControl {
    /**
     * @dev The `account` is missing a role.
     */
    error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);

    /**
     * @dev The caller of a function is not the expected one.
     *
     * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.
     */
    error AccessControlBadConfirmation();

    /**
     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     */
    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call, an admin role
     * bearer except when using {AccessControl-_setupRole}.
     */
    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) external view returns (bool);

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {AccessControl-_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) external view returns (bytes32);

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `callerConfirmation`.
     */
    function renounceRole(bytes32 role, address callerConfirmation) external;
}

File 10 of 12 : Context.sol
// 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;
    }
}

File 11 of 12 : ERC165.sol
// 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;
    }
}

File 12 of 12 : IERC165.sol
// 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);
}

Settings
{
  "remappings": [
    "@openzeppelin/=lib/openzeppelin-contracts/",
    "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
    "ds-test/=lib/openzeppelin-contracts/lib/forge-std/lib/ds-test/src/",
    "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
    "forge-std/=lib/forge-std/src/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "viaIR": false,
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"contract INFTRegistry","name":"_registry","type":"address"},{"internalType":"uint256","name":"_minCommitmentAge","type":"uint256"},{"internalType":"uint256","name":"_maxCommitmentAge","type":"uint256"},{"internalType":"contract IAggregatorInterface","name":"_usdOracle","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"CannotSetNewCharLengthAmounts","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"InsufficientValue","type":"error"},{"inputs":[{"internalType":"uint256","name":"duration","type":"uint256"}],"name":"InvalidDuration","type":"error"},{"inputs":[],"name":"MaxCommitmentAgeTooLow","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"UnauthorizedAddress","type":"error"},{"inputs":[{"internalType":"string","name":"label","type":"string"}],"name":"WrongNumberOfChars","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_address","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"AddressWithdrew","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"inputs":[],"name":"ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"charAmount","type":"uint256"}],"name":"addNextPriceForCharLength","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"available","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"charAmounts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"commitments","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"freeRegistrations","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLastCharIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"charLength","type":"uint16"}],"name":"getPriceDataForLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxChars","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxCommitmentAge","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxFreeRegistrations","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxRegistrationDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minChars","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minCommitmentAge","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minRegistrationDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"label","type":"string"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"duration","type":"uint256"}],"name":"register","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"string","name":"label","type":"string"},{"internalType":"uint256","name":"duration","type":"uint256"}],"name":"renew","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"label","type":"string"},{"internalType":"uint256","name":"duration","type":"uint256"}],"name":"rentPrice","outputs":[{"internalType":"uint256","name":"weiPrice","type":"uint256"},{"internalType":"uint256","name":"usdPrice","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxFreeRegistrations","type":"uint256"}],"name":"setMaxFreeRegistrations","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minRegistrationDuration","type":"uint256"},{"internalType":"uint256","name":"_maxRegistrationDuration","type":"uint256"},{"internalType":"uint16","name":"_minChars","type":"uint16"},{"internalType":"uint16","name":"_maxChars","type":"uint16"}],"name":"setParams","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_charAmounts","type":"uint256[]"}],"name":"setPricingForAllLengths","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_oracle","type":"address"}],"name":"setUSDOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"targetRegistry","outputs":[{"internalType":"contract INFTRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"addresses","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"updateFreeRegistrations","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"charLength","type":"uint16"},{"internalType":"uint256","name":"charAmount","type":"uint256"}],"name":"updatePriceForCharLength","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"usdOracle","outputs":[{"internalType":"contract IAggregatorInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60e06040523480156200001157600080fd5b5060405162001de138038062001de1833981016040819052620000349162000194565b6001600160a01b03841660c05282821162000062576040516307cb550760e31b815260040160405180910390fd5b608083905260a0829052600180546001600160a01b0319166001600160a01b03831617905562000094600033620000cc565b50620000c17fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177533620000cc565b5050505050620001e5565b6000828152602081815260408083206001600160a01b038516845290915281205460ff1662000171576000838152602081815260408083206001600160a01b03861684529091529020805460ff19166001179055620001283390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600162000175565b5060005b92915050565b6001600160a01b03811681146200019157600080fd5b50565b60008060008060808587031215620001ab57600080fd5b8451620001b8816200017b565b8094505060208501519250604085015191506060850151620001da816200017b565b939692955090935050565b60805160a05160c051611ba962000238600039600081816103bb01528181610ab301528181610c9001528181610d0901528181610e3601526111120152600061064e015260006104c10152611ba96000f3fe6080604052600436106101f95760003560e01c80638d839ffe1161010d578063acf1a841116100a0578063c9e871131161006f578063c9e8711314610626578063ce1e09c01461063c578063d393c87114610670578063d547741f14610683578063f967c88f146106a357600080fd5b8063acf1a841146105b3578063ba8d2479146105c6578063c48561fe146105e6578063c8a4271f1461060657600080fd5b806396e494e8116100dc57806396e494e81461053e5780639dbd62271461055e578063a0b90f001461057e578063a217fddf1461059e57600080fd5b80638d839ffe146104af57806391d14854146104e357806394e82a4c146105035780639612f9ce1461051e57600080fd5b8063444a2d8d11610190578063718df52a1161015f578063718df52a146103f557806375b238fc1461040b578063786930001461042d578063839df9451461044d57806383e7f6ff1461047a57600080fd5b8063444a2d8d14610335578063458174d1146103555780634dc80076146103755780636f09897a146103a957600080fd5b8063248a9ca3116101cc578063248a9ca3146102a55780632e1a7d4d146102d55780632f2ff15d146102f557806336568abe1461031557600080fd5b806301ffc9a7146101fe57806308993daa1461023357806312ee468a1461026e57806317d861ba14610283575b600080fd5b34801561020a57600080fd5b5061021e61021936600461162b565b6106b9565b60405190151581526020015b60405180910390f35b34801561023f57600080fd5b5061026061024e36600461166a565b60076020526000908152604090205481565b60405190815260200161022a565b34801561027a57600080fd5b506102606106f0565b34801561028f57600080fd5b506102a361029e366004611699565b610707565b005b3480156102b157600080fd5b506102606102c03660046116df565b60009081526020819052604090206001015490565b3480156102e157600080fd5b506102a36102f03660046116df565b610751565b34801561030157600080fd5b506102a36103103660046116f8565b6107b0565b34801561032157600080fd5b506102a36103303660046116f8565b6107db565b34801561034157600080fd5b506102606103503660046116df565b61080e565b34801561036157600080fd5b506102a361037036600461176d565b61082f565b34801561038157600080fd5b506004546103969062010000900461ffff1681565b60405161ffff909116815260200161022a565b3480156103b557600080fd5b506103dd7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161022a565b34801561040157600080fd5b5061026060085481565b34801561041757600080fd5b50610260600080516020611b5483398151915281565b34801561043957600080fd5b506102a36104483660046117d9565b61091e565b34801561045957600080fd5b506102606104683660046116df565b60066020526000908152604090205481565b34801561048657600080fd5b5061049a6104953660046118a6565b610992565b6040805192835260208301919091520161022a565b3480156104bb57600080fd5b506102607f000000000000000000000000000000000000000000000000000000000000000081565b3480156104ef57600080fd5b5061021e6104fe3660046116f8565b610a53565b34801561050f57600080fd5b506004546103969061ffff1681565b34801561052a57600080fd5b506102a36105393660046116df565b610a7c565b34801561054a57600080fd5b5061021e6105593660046116df565b610a9a565b34801561056a57600080fd5b506102606105793660046118eb565b610bcf565b34801561058a57600080fd5b506102a361059936600461166a565b610bfa565b3480156105aa57600080fd5b50610260600081565b6102a36105c13660046118a6565b610c35565b3480156105d257600080fd5b506102a36105e1366004611906565b610ee2565b3480156105f257600080fd5b506102a36106013660046116df565b610f12565b34801561061257600080fd5b506001546103dd906001600160a01b031681565b34801561063257600080fd5b5061026060025481565b34801561064857600080fd5b506102607f000000000000000000000000000000000000000000000000000000000000000081565b6102a361067e366004611948565b610f60565b34801561068f57600080fd5b506102a361069e3660046116f8565b6111a8565b3480156106af57600080fd5b5061026060035481565b60006001600160e01b03198216637965db0b60e01b14806106ea57506301ffc9a760e01b6001600160e01b03198316145b92915050565b600554600090610702906001906119b8565b905090565b600080516020611b5483398151915261071f816111cd565b506002939093556003919091556004805461ffff938416620100000263ffffffff199091169390921692909217179055565b600080516020611b54833981519152610769816111cd565b6040513390839082907fb990971c3785a76fb59cf6aa8fe8327738148e676c6d46a6dea040c4b6b2609590600090a36107ab6001600160a01b038216846111da565b505050565b6000828152602081905260409020600101546107cb816111cd565b6107d58383611271565b50505050565b6001600160a01b03811633146108045760405163334bd91960e11b815260040160405180910390fd5b6107ab8282611303565b6005818154811061081e57600080fd5b600091825260209091200154905081565b600080516020611b54833981519152610847816111cd565b83821461089b5760405162461bcd60e51b815260206004820152601e60248201527f417272617973206d757374206265207468652073616d65206c656e677468000060448201526064015b60405180910390fd5b60005b84811015610916578383828181106108b8576108b86119cb565b90506020020135600760008888858181106108d5576108d56119cb565b90506020020160208101906108ea919061166a565b6001600160a01b031681526020810191909152604001600020558061090e816119e1565b91505061089e565b505050505050565b600080516020611b54833981519152610936816111cd565b600554610945906001906119b8565b8361ffff161115610969576040516339b7567760e21b815260040160405180910390fd5b8160058461ffff1681548110610981576109816119cb565b600091825260209091200155505050565b60008060006109a08561136e565b60055490915060008115610a195781831015610a0557600583815481106109c9576109c96119cb565b9060005260206000200154905080600003610a005760056000815481106109f2576109f26119cb565b906000526020600020015490505b610a28565b60056000815481106109f2576109f26119cb565b60008094509450505050610a4c565b610a3a610a3587836119fa565b611471565b610a4487836119fa565b945094505050505b9250929050565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b600080516020611b54833981519152610a94816111cd565b50600855565b6040516331a9108f60e11b8152600481018290526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa925050508015610b1e575060408051601f3d908101601f19168201909252610b1b91810190611a11565b60015b610bc1573d808015610b4c576040519150601f19603f3d011682016040523d82523d6000602084013e610b51565b606091505b50604080516024808201869052825180830390910181526044909101909152602080820180516001600160e01b0316637e27328960e01b178152915190912082519183019190912003610ba75750600192915050565b8060405162461bcd60e51b81526004016108929190611a7e565b50600092915050565b919050565b600060058261ffff1681548110610be857610be86119cb565b90600052602060002001549050919050565b600080516020611b54833981519152610c12816111cd565b50600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000828051906020012060001c9050600083604051602001610c579190611a91565b60408051601f198184030181529082905280516020909101206352cc3b2160e01b82526004820181905291506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906352cc3b2190602401602060405180830381865afa158015610cd7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cfb9190611aad565b67ffffffffffffffff1690507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636352211e846040518263ffffffff1660e01b8152600401610d5591815260200190565b602060405180830381865afa158015610d72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d969190611a11565b6001600160a01b0316336001600160a01b031614610dca57604051632ce31dd560e01b815260048101849052602401610892565b600254841080610ddb575060035484115b15610dfc576040516313b783af60e21b815260048101859052602401610892565b6000610e088686610992565b50905080341015610e2c5760405163044044a560e21b815260040160405180910390fd5b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663c546b74884610e668886611ad7565b6040516001600160e01b031960e085901b168152600481019290925267ffffffffffffffff166024820152604401600060405180830381600087803b158015610eae57600080fd5b505af1158015610ec2573d6000803e3d6000fd5b505050508034111561091657610916610edb82346119b8565b33906111da565b600080516020611b54833981519152610efa816111cd565b610f06600560006115ad565b6107d5600584846115cb565b600080516020611b54833981519152610f2a816111cd565b50600580546001810182556000919091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00155565b600254811080610f71575060035481115b15610f92576040516313b783af60e21b815260048101829052602401610892565b610f9b8361150d565b610fba5782604051637df0e75560e01b81526004016108929190611a7e565b6000610fc68483610992565b509050806000036110e7576008543360009081526007602052604090205410158061100b57506008546001600160a01b03841660009081526007602052604090205410155b156110585760405162461bcd60e51b815260206004820152601f60248201527f4d6178206672656520726567697374726174696f6e73206578636565646564006044820152606401610892565b6001600160a01b038316330361109357336000908152600760205260408120805460019290611088908490611ad7565b909155506110e79050565b3360009081526007602052604081208054600192906110b3908490611ad7565b90915550506001600160a01b03831660009081526007602052604081208054600192906110e1908490611ad7565b90915550505b803410156111085760405163044044a560e21b815260040160405180910390fd5b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663d393c87185856111438642611ad7565b6040518463ffffffff1660e01b815260040161116193929190611aea565b600060405180830381600087803b15801561117b57600080fd5b505af115801561118f573d6000803e3d6000fd5b50505050803411156107d5576107d5610edb82346119b8565b6000828152602081905260409020600101546111c3816111cd565b6107d58383611303565b6111d78133611570565b50565b804710156111fd5760405163cd78605960e01b8152306004820152602401610892565b6000826001600160a01b03168260405160006040518083038185875af1925050503d806000811461124a576040519150601f19603f3d011682016040523d82523d6000602084013e61124f565b606091505b50509050806107ab57604051630a12f52160e11b815260040160405180910390fd5b600061127d8383610a53565b6112fb576000838152602081815260408083206001600160a01b03861684529091529020805460ff191660011790556112b33390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45060016106ea565b5060006106ea565b600061130f8383610a53565b156112fb576000838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45060016106ea565b8051600090819081905b80821015611468576000858381518110611394576113946119cb565b01602001516001600160f81b0319169050600160ff1b8110156113c3576113bc600184611ad7565b9250611455565b600760fd1b6001600160f81b0319821610156113e4576113bc600284611ad7565b600f60fc1b6001600160f81b031982161015611405576113bc600384611ad7565b601f60fb1b6001600160f81b031982161015611426576113bc600484611ad7565b603f60fa1b6001600160f81b031982161015611447576113bc600584611ad7565b611452600684611ad7565b92505b5082611460816119e1565b935050611378565b50909392505050565b600080600160009054906101000a90046001600160a01b03166001600160a01b03166350d25bcd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114eb9190611b18565b9050806114fc846305f5e1006119fa565b6115069190611b31565b9392505050565b60045460009061ffff166115208361136e565b106115685760045462010000900461ffff1615801590611553575060045462010000900461ffff166115518361136e565b115b1561156057506000919050565b506001919050565b506000919050565b61157a8282610a53565b6115a95760405163e2517d3f60e01b81526001600160a01b038216600482015260248101839052604401610892565b5050565b50805460008255906000526020600020908101906111d79190611616565b828054828255906000526020600020908101928215611606579160200282015b828111156116065782358255916020019190600101906115eb565b50611612929150611616565b5090565b5b808211156116125760008155600101611617565b60006020828403121561163d57600080fd5b81356001600160e01b03198116811461150657600080fd5b6001600160a01b03811681146111d757600080fd5b60006020828403121561167c57600080fd5b813561150681611655565b803561ffff81168114610bca57600080fd5b600080600080608085870312156116af57600080fd5b84359350602085013592506116c660408601611687565b91506116d460608601611687565b905092959194509250565b6000602082840312156116f157600080fd5b5035919050565b6000806040838503121561170b57600080fd5b82359150602083013561171d81611655565b809150509250929050565b60008083601f84011261173a57600080fd5b50813567ffffffffffffffff81111561175257600080fd5b6020830191508360208260051b8501011115610a4c57600080fd5b6000806000806040858703121561178357600080fd5b843567ffffffffffffffff8082111561179b57600080fd5b6117a788838901611728565b909650945060208701359150808211156117c057600080fd5b506117cd87828801611728565b95989497509550505050565b600080604083850312156117ec57600080fd5b6117f583611687565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261182a57600080fd5b813567ffffffffffffffff8082111561184557611845611803565b604051601f8301601f19908116603f0116810190828211818310171561186d5761186d611803565b8160405283815286602085880101111561188657600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080604083850312156118b957600080fd5b823567ffffffffffffffff8111156118d057600080fd5b6118dc85828601611819565b95602094909401359450505050565b6000602082840312156118fd57600080fd5b61150682611687565b6000806020838503121561191957600080fd5b823567ffffffffffffffff81111561193057600080fd5b61193c85828601611728565b90969095509350505050565b60008060006060848603121561195d57600080fd5b833567ffffffffffffffff81111561197457600080fd5b61198086828701611819565b935050602084013561199181611655565b929592945050506040919091013590565b634e487b7160e01b600052601160045260246000fd5b818103818111156106ea576106ea6119a2565b634e487b7160e01b600052603260045260246000fd5b6000600182016119f3576119f36119a2565b5060010190565b80820281158282048414176106ea576106ea6119a2565b600060208284031215611a2357600080fd5b815161150681611655565b60005b83811015611a49578181015183820152602001611a31565b50506000910152565b60008151808452611a6a816020860160208601611a2e565b601f01601f19169290920160200192915050565b6020815260006115066020830184611a52565b60008251611aa3818460208701611a2e565b9190910192915050565b600060208284031215611abf57600080fd5b815167ffffffffffffffff8116811461150657600080fd5b808201808211156106ea576106ea6119a2565b606081526000611afd6060830186611a52565b6001600160a01b039490941660208301525060400152919050565b600060208284031215611b2a57600080fd5b5051919050565b600082611b4e57634e487b7160e01b600052601260045260246000fd5b50049056fea49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775a26469706673582212209296807fadb324120159400c6a310fa296aeda44512e806c436bb61b762db6e664736f6c634300081400330000000000000000000000002d10c15cc0885b97d7c9356194b55b2add051d0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000078000000000000000000000000ab594600376ec9fd91f8e885dadf0ce036862de0

Deployed Bytecode

0x6080604052600436106101f95760003560e01c80638d839ffe1161010d578063acf1a841116100a0578063c9e871131161006f578063c9e8711314610626578063ce1e09c01461063c578063d393c87114610670578063d547741f14610683578063f967c88f146106a357600080fd5b8063acf1a841146105b3578063ba8d2479146105c6578063c48561fe146105e6578063c8a4271f1461060657600080fd5b806396e494e8116100dc57806396e494e81461053e5780639dbd62271461055e578063a0b90f001461057e578063a217fddf1461059e57600080fd5b80638d839ffe146104af57806391d14854146104e357806394e82a4c146105035780639612f9ce1461051e57600080fd5b8063444a2d8d11610190578063718df52a1161015f578063718df52a146103f557806375b238fc1461040b578063786930001461042d578063839df9451461044d57806383e7f6ff1461047a57600080fd5b8063444a2d8d14610335578063458174d1146103555780634dc80076146103755780636f09897a146103a957600080fd5b8063248a9ca3116101cc578063248a9ca3146102a55780632e1a7d4d146102d55780632f2ff15d146102f557806336568abe1461031557600080fd5b806301ffc9a7146101fe57806308993daa1461023357806312ee468a1461026e57806317d861ba14610283575b600080fd5b34801561020a57600080fd5b5061021e61021936600461162b565b6106b9565b60405190151581526020015b60405180910390f35b34801561023f57600080fd5b5061026061024e36600461166a565b60076020526000908152604090205481565b60405190815260200161022a565b34801561027a57600080fd5b506102606106f0565b34801561028f57600080fd5b506102a361029e366004611699565b610707565b005b3480156102b157600080fd5b506102606102c03660046116df565b60009081526020819052604090206001015490565b3480156102e157600080fd5b506102a36102f03660046116df565b610751565b34801561030157600080fd5b506102a36103103660046116f8565b6107b0565b34801561032157600080fd5b506102a36103303660046116f8565b6107db565b34801561034157600080fd5b506102606103503660046116df565b61080e565b34801561036157600080fd5b506102a361037036600461176d565b61082f565b34801561038157600080fd5b506004546103969062010000900461ffff1681565b60405161ffff909116815260200161022a565b3480156103b557600080fd5b506103dd7f0000000000000000000000002d10c15cc0885b97d7c9356194b55b2add051d0181565b6040516001600160a01b03909116815260200161022a565b34801561040157600080fd5b5061026060085481565b34801561041757600080fd5b50610260600080516020611b5483398151915281565b34801561043957600080fd5b506102a36104483660046117d9565b61091e565b34801561045957600080fd5b506102606104683660046116df565b60066020526000908152604090205481565b34801561048657600080fd5b5061049a6104953660046118a6565b610992565b6040805192835260208301919091520161022a565b3480156104bb57600080fd5b506102607f000000000000000000000000000000000000000000000000000000000000000081565b3480156104ef57600080fd5b5061021e6104fe3660046116f8565b610a53565b34801561050f57600080fd5b506004546103969061ffff1681565b34801561052a57600080fd5b506102a36105393660046116df565b610a7c565b34801561054a57600080fd5b5061021e6105593660046116df565b610a9a565b34801561056a57600080fd5b506102606105793660046118eb565b610bcf565b34801561058a57600080fd5b506102a361059936600461166a565b610bfa565b3480156105aa57600080fd5b50610260600081565b6102a36105c13660046118a6565b610c35565b3480156105d257600080fd5b506102a36105e1366004611906565b610ee2565b3480156105f257600080fd5b506102a36106013660046116df565b610f12565b34801561061257600080fd5b506001546103dd906001600160a01b031681565b34801561063257600080fd5b5061026060025481565b34801561064857600080fd5b506102607f000000000000000000000000000000000000000000000000000000000000007881565b6102a361067e366004611948565b610f60565b34801561068f57600080fd5b506102a361069e3660046116f8565b6111a8565b3480156106af57600080fd5b5061026060035481565b60006001600160e01b03198216637965db0b60e01b14806106ea57506301ffc9a760e01b6001600160e01b03198316145b92915050565b600554600090610702906001906119b8565b905090565b600080516020611b5483398151915261071f816111cd565b506002939093556003919091556004805461ffff938416620100000263ffffffff199091169390921692909217179055565b600080516020611b54833981519152610769816111cd565b6040513390839082907fb990971c3785a76fb59cf6aa8fe8327738148e676c6d46a6dea040c4b6b2609590600090a36107ab6001600160a01b038216846111da565b505050565b6000828152602081905260409020600101546107cb816111cd565b6107d58383611271565b50505050565b6001600160a01b03811633146108045760405163334bd91960e11b815260040160405180910390fd5b6107ab8282611303565b6005818154811061081e57600080fd5b600091825260209091200154905081565b600080516020611b54833981519152610847816111cd565b83821461089b5760405162461bcd60e51b815260206004820152601e60248201527f417272617973206d757374206265207468652073616d65206c656e677468000060448201526064015b60405180910390fd5b60005b84811015610916578383828181106108b8576108b86119cb565b90506020020135600760008888858181106108d5576108d56119cb565b90506020020160208101906108ea919061166a565b6001600160a01b031681526020810191909152604001600020558061090e816119e1565b91505061089e565b505050505050565b600080516020611b54833981519152610936816111cd565b600554610945906001906119b8565b8361ffff161115610969576040516339b7567760e21b815260040160405180910390fd5b8160058461ffff1681548110610981576109816119cb565b600091825260209091200155505050565b60008060006109a08561136e565b60055490915060008115610a195781831015610a0557600583815481106109c9576109c96119cb565b9060005260206000200154905080600003610a005760056000815481106109f2576109f26119cb565b906000526020600020015490505b610a28565b60056000815481106109f2576109f26119cb565b60008094509450505050610a4c565b610a3a610a3587836119fa565b611471565b610a4487836119fa565b945094505050505b9250929050565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b600080516020611b54833981519152610a94816111cd565b50600855565b6040516331a9108f60e11b8152600481018290526000907f0000000000000000000000002d10c15cc0885b97d7c9356194b55b2add051d016001600160a01b031690636352211e90602401602060405180830381865afa925050508015610b1e575060408051601f3d908101601f19168201909252610b1b91810190611a11565b60015b610bc1573d808015610b4c576040519150601f19603f3d011682016040523d82523d6000602084013e610b51565b606091505b50604080516024808201869052825180830390910181526044909101909152602080820180516001600160e01b0316637e27328960e01b178152915190912082519183019190912003610ba75750600192915050565b8060405162461bcd60e51b81526004016108929190611a7e565b50600092915050565b919050565b600060058261ffff1681548110610be857610be86119cb565b90600052602060002001549050919050565b600080516020611b54833981519152610c12816111cd565b50600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000828051906020012060001c9050600083604051602001610c579190611a91565b60408051601f198184030181529082905280516020909101206352cc3b2160e01b82526004820181905291506000906001600160a01b037f0000000000000000000000002d10c15cc0885b97d7c9356194b55b2add051d0116906352cc3b2190602401602060405180830381865afa158015610cd7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cfb9190611aad565b67ffffffffffffffff1690507f0000000000000000000000002d10c15cc0885b97d7c9356194b55b2add051d016001600160a01b0316636352211e846040518263ffffffff1660e01b8152600401610d5591815260200190565b602060405180830381865afa158015610d72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d969190611a11565b6001600160a01b0316336001600160a01b031614610dca57604051632ce31dd560e01b815260048101849052602401610892565b600254841080610ddb575060035484115b15610dfc576040516313b783af60e21b815260048101859052602401610892565b6000610e088686610992565b50905080341015610e2c5760405163044044a560e21b815260040160405180910390fd5b6001600160a01b037f0000000000000000000000002d10c15cc0885b97d7c9356194b55b2add051d011663c546b74884610e668886611ad7565b6040516001600160e01b031960e085901b168152600481019290925267ffffffffffffffff166024820152604401600060405180830381600087803b158015610eae57600080fd5b505af1158015610ec2573d6000803e3d6000fd5b505050508034111561091657610916610edb82346119b8565b33906111da565b600080516020611b54833981519152610efa816111cd565b610f06600560006115ad565b6107d5600584846115cb565b600080516020611b54833981519152610f2a816111cd565b50600580546001810182556000919091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00155565b600254811080610f71575060035481115b15610f92576040516313b783af60e21b815260048101829052602401610892565b610f9b8361150d565b610fba5782604051637df0e75560e01b81526004016108929190611a7e565b6000610fc68483610992565b509050806000036110e7576008543360009081526007602052604090205410158061100b57506008546001600160a01b03841660009081526007602052604090205410155b156110585760405162461bcd60e51b815260206004820152601f60248201527f4d6178206672656520726567697374726174696f6e73206578636565646564006044820152606401610892565b6001600160a01b038316330361109357336000908152600760205260408120805460019290611088908490611ad7565b909155506110e79050565b3360009081526007602052604081208054600192906110b3908490611ad7565b90915550506001600160a01b03831660009081526007602052604081208054600192906110e1908490611ad7565b90915550505b803410156111085760405163044044a560e21b815260040160405180910390fd5b6001600160a01b037f0000000000000000000000002d10c15cc0885b97d7c9356194b55b2add051d011663d393c87185856111438642611ad7565b6040518463ffffffff1660e01b815260040161116193929190611aea565b600060405180830381600087803b15801561117b57600080fd5b505af115801561118f573d6000803e3d6000fd5b50505050803411156107d5576107d5610edb82346119b8565b6000828152602081905260409020600101546111c3816111cd565b6107d58383611303565b6111d78133611570565b50565b804710156111fd5760405163cd78605960e01b8152306004820152602401610892565b6000826001600160a01b03168260405160006040518083038185875af1925050503d806000811461124a576040519150601f19603f3d011682016040523d82523d6000602084013e61124f565b606091505b50509050806107ab57604051630a12f52160e11b815260040160405180910390fd5b600061127d8383610a53565b6112fb576000838152602081815260408083206001600160a01b03861684529091529020805460ff191660011790556112b33390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45060016106ea565b5060006106ea565b600061130f8383610a53565b156112fb576000838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45060016106ea565b8051600090819081905b80821015611468576000858381518110611394576113946119cb565b01602001516001600160f81b0319169050600160ff1b8110156113c3576113bc600184611ad7565b9250611455565b600760fd1b6001600160f81b0319821610156113e4576113bc600284611ad7565b600f60fc1b6001600160f81b031982161015611405576113bc600384611ad7565b601f60fb1b6001600160f81b031982161015611426576113bc600484611ad7565b603f60fa1b6001600160f81b031982161015611447576113bc600584611ad7565b611452600684611ad7565b92505b5082611460816119e1565b935050611378565b50909392505050565b600080600160009054906101000a90046001600160a01b03166001600160a01b03166350d25bcd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114eb9190611b18565b9050806114fc846305f5e1006119fa565b6115069190611b31565b9392505050565b60045460009061ffff166115208361136e565b106115685760045462010000900461ffff1615801590611553575060045462010000900461ffff166115518361136e565b115b1561156057506000919050565b506001919050565b506000919050565b61157a8282610a53565b6115a95760405163e2517d3f60e01b81526001600160a01b038216600482015260248101839052604401610892565b5050565b50805460008255906000526020600020908101906111d79190611616565b828054828255906000526020600020908101928215611606579160200282015b828111156116065782358255916020019190600101906115eb565b50611612929150611616565b5090565b5b808211156116125760008155600101611617565b60006020828403121561163d57600080fd5b81356001600160e01b03198116811461150657600080fd5b6001600160a01b03811681146111d757600080fd5b60006020828403121561167c57600080fd5b813561150681611655565b803561ffff81168114610bca57600080fd5b600080600080608085870312156116af57600080fd5b84359350602085013592506116c660408601611687565b91506116d460608601611687565b905092959194509250565b6000602082840312156116f157600080fd5b5035919050565b6000806040838503121561170b57600080fd5b82359150602083013561171d81611655565b809150509250929050565b60008083601f84011261173a57600080fd5b50813567ffffffffffffffff81111561175257600080fd5b6020830191508360208260051b8501011115610a4c57600080fd5b6000806000806040858703121561178357600080fd5b843567ffffffffffffffff8082111561179b57600080fd5b6117a788838901611728565b909650945060208701359150808211156117c057600080fd5b506117cd87828801611728565b95989497509550505050565b600080604083850312156117ec57600080fd5b6117f583611687565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261182a57600080fd5b813567ffffffffffffffff8082111561184557611845611803565b604051601f8301601f19908116603f0116810190828211818310171561186d5761186d611803565b8160405283815286602085880101111561188657600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080604083850312156118b957600080fd5b823567ffffffffffffffff8111156118d057600080fd5b6118dc85828601611819565b95602094909401359450505050565b6000602082840312156118fd57600080fd5b61150682611687565b6000806020838503121561191957600080fd5b823567ffffffffffffffff81111561193057600080fd5b61193c85828601611728565b90969095509350505050565b60008060006060848603121561195d57600080fd5b833567ffffffffffffffff81111561197457600080fd5b61198086828701611819565b935050602084013561199181611655565b929592945050506040919091013590565b634e487b7160e01b600052601160045260246000fd5b818103818111156106ea576106ea6119a2565b634e487b7160e01b600052603260045260246000fd5b6000600182016119f3576119f36119a2565b5060010190565b80820281158282048414176106ea576106ea6119a2565b600060208284031215611a2357600080fd5b815161150681611655565b60005b83811015611a49578181015183820152602001611a31565b50506000910152565b60008151808452611a6a816020860160208601611a2e565b601f01601f19169290920160200192915050565b6020815260006115066020830184611a52565b60008251611aa3818460208701611a2e565b9190910192915050565b600060208284031215611abf57600080fd5b815167ffffffffffffffff8116811461150657600080fd5b808201808211156106ea576106ea6119a2565b606081526000611afd6060830186611a52565b6001600160a01b039490941660208301525060400152919050565b600060208284031215611b2a57600080fd5b5051919050565b600082611b4e57634e487b7160e01b600052601260045260246000fd5b50049056fea49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775a26469706673582212209296807fadb324120159400c6a310fa296aeda44512e806c436bb61b762db6e664736f6c63430008140033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

0000000000000000000000002d10c15cc0885b97d7c9356194b55b2add051d0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000078000000000000000000000000ab594600376ec9fd91f8e885dadf0ce036862de0

-----Decoded View---------------
Arg [0] : _registry (address): 0x2d10c15Cc0885B97D7C9356194b55b2Add051D01
Arg [1] : _minCommitmentAge (uint256): 0
Arg [2] : _maxCommitmentAge (uint256): 120
Arg [3] : _usdOracle (address): 0xAB594600376Ec9fD91F8e885dADF0CE036862dE0

-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000002d10c15cc0885b97d7c9356194b55b2add051d01
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000078
Arg [3] : 000000000000000000000000ab594600376ec9fd91f8e885dadf0ce036862de0


Block Transaction Gas Used Reward
view all blocks produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
[ 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.