false
false
0
The new Blockscout UI is now open source! Learn how to deploy it here
- We're indexing this chain right now. Some of the counts may be inaccurate.

Contract Address Details

0x11f3e4d4457ABF1e04149Ce865604afeeD9E93C2

Contract Name
EVMFSRegistry
Creator
0xde984b–d986ce at 0xd4e444–49ff21
Balance
0.015 ETH
Tokens
Fetching tokens...
Transactions
Fetching transactions...
Transfers
Fetching transfers...
Gas Used
Fetching gas used...
Last Balance Update
5620969
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
Contract name:
EVMFSRegistry




Optimization enabled
true
Compiler version
v0.8.28+commit.7893614a




Optimization runs
200
EVM Version
prague




Verified at
2026-03-10T21:51:56.094864Z

contracts/EVMFSRegistry.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import "@openzeppelin/contracts/access/Ownable.sol";
import "./IEVMFSRegistry.sol";

/**
 * @title EVMFSRegistry
 * @notice On-chain name→CID registry for the evmfs.app subdomain gateway.
 *
 * Users pay a one-time fee (based on name length) to claim a name.
 * The owner of a name can update its CID at any time (enabling site updates)
 * and transfer ownership to another address.
 *
 * Pricing follows a linear-scarcity curve by UTF-8 byte length:
 *   1 char  →  10   ETH
 *   2 chars →   3   ETH
 *   3 chars →   1   ETH
 *   4 chars →   0.3  ETH
 *   5 chars →   0.1  ETH
 *   6 chars →   0.03 ETH
 *   7+ chars→   0.015 ETH
 *
 * On testnets these are testnet ETH — same ratios for integration testing.
 */
contract EVMFSRegistry is Ownable, IEVMFSRegistry {
    // ─────────────────────────────────────────────────────
    //  Storage
    // ─────────────────────────────────────────────────────

    /// @dev name hash → 32-byte EVMFS CID (raw sha256)
    mapping(bytes32 => bytes) private _nameToCid;

    /// @dev name hash → owner address
    mapping(bytes32 => address) private _nameOwner;

    /// @dev name hash → original plaintext name (for enumeration / display)
    mapping(bytes32 => string) private _nameLabel;

    uint256 private _nameCount;

    // ─────────────────────────────────────────────────────
    //  Events
    // ─────────────────────────────────────────────────────

    event NameRegistered(string indexed nameHash, string name, address indexed owner, bytes cid);
    event CidUpdated(string indexed nameHash, string name, bytes oldCid, bytes newCid);
    event NameTransferred(string indexed nameHash, string name, address indexed from, address indexed to);

    // ─────────────────────────────────────────────────────
    //  Errors
    // ─────────────────────────────────────────────────────

    error NameAlreadyTaken();
    error NameNotRegistered();
    error NotNameOwner();
    error InsufficientFee();
    error EmptyName();
    error EmptyCid();
    error InvalidCidLength();
    error TransferToZero();

    // ─────────────────────────────────────────────────────
    //  Constructor
    // ─────────────────────────────────────────────────────

    constructor() Ownable(msg.sender) {}

    // ─────────────────────────────────────────────────────
    //  Write — Registration
    // ─────────────────────────────────────────────────────

    /**
     * @notice Register a name and bind it to an EVMFS CID.
     * @param name  Plaintext name (e.g. "myapp"). Must be non-empty.
     * @param cid   32-byte EVMFS CID (rolling SHA-256 hash).
     */
    function registerApp(string calldata name, bytes calldata cid) external payable {
        if (bytes(name).length == 0) revert EmptyName();
        if (cid.length == 0) revert EmptyCid();
        if (cid.length != 32) revert InvalidCidLength();

        bytes32 key = _nameKey(name);
        if (_nameOwner[key] != address(0)) revert NameAlreadyTaken();

        uint256 price = getPrice(name);
        if (msg.value < price) revert InsufficientFee();

        _nameOwner[key] = msg.sender;
        _nameToCid[key] = cid;
        _nameLabel[key] = name;
        _nameCount++;

        // Refund overpayment
        uint256 excess = msg.value - price;
        if (excess > 0) {
            (bool ok, ) = msg.sender.call{value: excess}("");
            require(ok, "Refund failed");
        }

        emit NameRegistered(name, name, msg.sender, cid);
    }

    // ─────────────────────────────────────────────────────
    //  Write — Update CID
    // ─────────────────────────────────────────────────────

    /**
     * @notice Update the CID for a name you own (deploy a new version).
     * @param name  The registered name.
     * @param cid   New 32-byte EVMFS CID.
     */
    function updateCid(string calldata name, bytes calldata cid) external {
        if (cid.length == 0) revert EmptyCid();
        if (cid.length != 32) revert InvalidCidLength();

        bytes32 key = _nameKey(name);
        if (_nameOwner[key] == address(0)) revert NameNotRegistered();
        if (_nameOwner[key] != msg.sender) revert NotNameOwner();

        bytes memory oldCid = _nameToCid[key];
        _nameToCid[key] = cid;

        emit CidUpdated(name, name, oldCid, cid);
    }

    // ─────────────────────────────────────────────────────
    //  Write — Transfer ownership
    // ─────────────────────────────────────────────────────

    /**
     * @notice Transfer ownership of a name to a new address.
     * @param name      The registered name.
     * @param newOwner  The new owner. Cannot be address(0).
     */
    function transferName(string calldata name, address newOwner) external {
        if (newOwner == address(0)) revert TransferToZero();

        bytes32 key = _nameKey(name);
        if (_nameOwner[key] == address(0)) revert NameNotRegistered();
        if (_nameOwner[key] != msg.sender) revert NotNameOwner();

        address oldOwner = _nameOwner[key];
        _nameOwner[key] = newOwner;

        emit NameTransferred(name, name, oldOwner, newOwner);
    }

    // ─────────────────────────────────────────────────────
    //  Write — Admin
    // ─────────────────────────────────────────────────────

    /**
     * @notice Withdraw accumulated registration fees.
     */
    function withdraw() external onlyOwner {
        uint256 bal = address(this).balance;
        require(bal > 0, "Nothing to withdraw");
        (bool ok, ) = owner().call{value: bal}("");
        require(ok, "Withdraw failed");
    }

    // ─────────────────────────────────────────────────────
    //  Read — IEVMFSRegistry
    // ─────────────────────────────────────────────────────

    /// @inheritdoc IEVMFSRegistry
    function getCid(string calldata name) external view returns (bytes memory) {
        return _nameToCid[_nameKey(name)];
    }

    /// @inheritdoc IEVMFSRegistry
    function nameOwner(string calldata name) external view returns (address) {
        return _nameOwner[_nameKey(name)];
    }

    /// @inheritdoc IEVMFSRegistry
    function isRegistered(string calldata name) external view returns (bool) {
        return _nameOwner[_nameKey(name)] != address(0);
    }

    /**
     * @inheritdoc IEVMFSRegistry
     * @notice Pricing by UTF-8 byte length (linear scarcity):
     *   1 →  10 ether    |  2 →  3 ether     |  3 →  1 ether
     *   4 →  0.3 ether   |  5 →  0.1 ether   |  6 →  0.03 ether
     *   7+ → 0.015 ether
     */
    function getPrice(string calldata name) public pure returns (uint256) {
        uint256 L = bytes(name).length;
        if (L == 0) return type(uint256).max; // Unreachable for valid calls
        if (L == 1) return 10 ether;
        if (L == 2) return 3 ether;
        if (L == 3) return 1 ether;
        if (L == 4) return 0.3 ether;
        if (L == 5) return 0.1 ether;
        if (L == 6) return 0.03 ether;
        return 0.015 ether;
    }

    /// @notice Total number of registered names.
    function nameCount() external view returns (uint256) {
        return _nameCount;
    }

    // ─────────────────────────────────────────────────────
    //  Internal
    // ─────────────────────────────────────────────────────

    /// @dev Convert a plaintext name to a storage key via keccak256.
    function _nameKey(string calldata name) internal pure returns (bytes32) {
        return keccak256(bytes(name));
    }
}
        

../../lib/openzeppelin-contracts/contracts/access/Ownable.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;

import {Context} from "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * The initial owner is set to the address provided by the deployer. This can
 * later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}
          

../../lib/openzeppelin-contracts/contracts/utils/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;
    }
}
          

contracts/IEVMFSRegistry.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

/**
 * @title IEVMFSRegistry
 * @notice Interface for the EVMFS name registry.
 *         Maps human-readable names to EVMFS CIDs for subdomain resolution
 *         on evmfs.app (contract registry) and evmfs.link (ENS mirror).
 */
interface IEVMFSRegistry {
    /// @notice Returns the 32-byte CID bound to a name, or empty bytes if unregistered.
    function getCid(string calldata name) external view returns (bytes memory);

    /// @notice Returns the owner address of a registered name.
    function nameOwner(string calldata name) external view returns (address);

    /// @notice Returns the registration fee for a name based on its UTF-8 byte length.
    function getPrice(string calldata name) external pure returns (uint256);

    /// @notice Returns true if the name has been claimed.
    function isRegistered(string calldata name) external view returns (bool);
}
          

Compiler Settings

{"viaIR":true,"remappings":["@openzeppelin/contracts/=../../lib/openzeppelin-contracts/contracts/","forge-std/=../../lib/forge-std/src/","erc4626-tests/=/Users/Onix.Martinez/BlockProjects/web3-twitter/new_monorepo/lib/openzeppelin-contracts/lib/erc4626-tests/","halmos-cheatcodes/=/Users/Onix.Martinez/BlockProjects/web3-twitter/new_monorepo/lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/","openzeppelin-contracts/=/Users/Onix.Martinez/BlockProjects/web3-twitter/new_monorepo/lib/openzeppelin-contracts/contracts/"],"outputSelection":{"*":{"*":["*"],"":["*"]}},"optimizer":{"runs":200,"enabled":true},"metadata":{"useLiteralContent":false,"bytecodeHash":"ipfs","appendCBOR":true},"libraries":{},"evmVersion":"prague"}
              

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[]},{"type":"error","name":"EmptyCid","inputs":[]},{"type":"error","name":"EmptyName","inputs":[]},{"type":"error","name":"InsufficientFee","inputs":[]},{"type":"error","name":"InvalidCidLength","inputs":[]},{"type":"error","name":"NameAlreadyTaken","inputs":[]},{"type":"error","name":"NameNotRegistered","inputs":[]},{"type":"error","name":"NotNameOwner","inputs":[]},{"type":"error","name":"OwnableInvalidOwner","inputs":[{"type":"address","name":"owner","internalType":"address"}]},{"type":"error","name":"OwnableUnauthorizedAccount","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"error","name":"TransferToZero","inputs":[]},{"type":"event","name":"CidUpdated","inputs":[{"type":"string","name":"nameHash","internalType":"string","indexed":true},{"type":"string","name":"name","internalType":"string","indexed":false},{"type":"bytes","name":"oldCid","internalType":"bytes","indexed":false},{"type":"bytes","name":"newCid","internalType":"bytes","indexed":false}],"anonymous":false},{"type":"event","name":"NameRegistered","inputs":[{"type":"string","name":"nameHash","internalType":"string","indexed":true},{"type":"string","name":"name","internalType":"string","indexed":false},{"type":"address","name":"owner","internalType":"address","indexed":true},{"type":"bytes","name":"cid","internalType":"bytes","indexed":false}],"anonymous":false},{"type":"event","name":"NameTransferred","inputs":[{"type":"string","name":"nameHash","internalType":"string","indexed":true},{"type":"string","name":"name","internalType":"string","indexed":false},{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes","name":"","internalType":"bytes"}],"name":"getCid","inputs":[{"type":"string","name":"name","internalType":"string"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getPrice","inputs":[{"type":"string","name":"name","internalType":"string"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isRegistered","inputs":[{"type":"string","name":"name","internalType":"string"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"nameCount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"nameOwner","inputs":[{"type":"string","name":"name","internalType":"string"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"payable","outputs":[],"name":"registerApp","inputs":[{"type":"string","name":"name","internalType":"string"},{"type":"bytes","name":"cid","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferName","inputs":[{"type":"string","name":"name","internalType":"string"},{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateCid","inputs":[{"type":"string","name":"name","internalType":"string"},{"type":"bytes","name":"cid","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdraw","inputs":[]}]
              

Contract Creation Code

0x608080604052346071573315605e575f8054336001600160a01b0319821681178355916001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a3610e3490816100768239f35b631e4fbdf760e01b5f525f60045260245ffd5b5f80fdfe60806040526004361015610011575f80fd5b5f3560e01c806333e17c6014610a6057806337194d1e146109415780633ccfd60b1461088f57806343c2ee35146105fc578063524f3889146105b9578063715018a61461056257806373ff93a2146105455780638da5cb5b1461051e578063b4970b0f146101d4578063c822d7f014610181578063e18c3a061461012a5763f2fde38b1461009d575f80fd5b34610126576020366003190112610126576004356001600160a01b03811690819003610126576100cb610dd8565b8015610113575f80546001600160a01b03198116831782556001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a3005b631e4fbdf760e01b5f525f60045260245ffd5b5f80fd5b34610126576020366003190112610126576004356001600160401b0381116101265761015d610163913690600401610b57565b90610d9d565b5f526002602052602060018060a01b0360405f205416604051908152f35b34610126576020366003190112610126576004356001600160401b0381116101265761015d6101b4913690600401610b57565b5f526002602052602060018060a01b0360405f2054161515604051908152f35b6101dd36610ba8565b919092811561050f57821561050057602083036104f2576101fe8282610d9d565b5f818152600260205260409020546001600160a01b03166104e3576102238383610d0a565b908134106104d5575f81815260026020908152604080832080546001600160a01b03191633179055600190915290206001600160401b038611610452576102748661026e8354610bf8565b83610cbb565b5f86601f811160011461047157806102a0925f91610466575b508160011b915f199060031b1c19161790565b90555b5f52600360205260405f206001600160401b038411610452576102ca8461026e8354610bf8565b5f84601f81116001146103ef57806102f5925f916103e457508160011b915f199060031b1c19161790565b90555b6004545f1981146103d057600101600455803403903482116103d057340361037f575b507ffcd420f3c377ac516f77699a9c2a3d4109d0d28c17592854ca16517be96a77489161037a60405182848237808381015f81520390209461036a604051948594604086526040860191610c51565b9083820360208501523397610c51565b0390a3005b5f80808093335af161038f610c8c565b501561039b578461031b565b60405162461bcd60e51b815260206004820152600d60248201526c1499599d5b990819985a5b1959609a1b6044820152606490fd5b634e487b7160e01b5f52601160045260245ffd5b90508501358961028d565b50601f19851690825f528560205f20925f5b81811061043757501061041e575b5050600184811b0190556102f8565b8401355f19600387901b60f8161c19169055868061040f565b87840135855560019094019360209384019389935001610401565b634e487b7160e01b5f52604160045260245ffd5b90508901358a61028d565b50601f19871690825f528760205f20925f5b8b8282106104bb575050106104a2575b5050600186811b0190556102a3565b8801355f19600389901b60f8161c191690558780610493565b84013585556001909401936020938401938b935001610483565b62976f7560e21b5f5260045ffd5b630d706ecd60e21b5f5260045ffd5b6211911b60e81b5f5260045ffd5b636d91186360e01b5f5260045ffd5b632ef1310560e01b5f5260045ffd5b34610126575f366003190112610126575f546040516001600160a01b039091168152602090f35b34610126575f366003190112610126576020600454604051908152f35b34610126575f3660031901126101265761057a610dd8565b5f80546001600160a01b0319811682556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b34610126576020366003190112610126576004356001600160401b038111610126576105f46105ee6020923690600401610b57565b90610d0a565b604051908152f35b346101265761060a36610ba8565b929091831561050057602084036104f2576106258183610d9d565b5f818152600260205260409020549093906001600160a01b031615610880575f848152600260205260409020546001600160a01b0316330361087157835f52600160205260405f209360405194855f82549261068084610bf8565b808452936001811690811561084f575060011461080b575b506106a592500386610c30565b5f52600160205260405f20946001600160401b038111610452576106d3816106cd8854610bf8565b88610cbb565b5f95601f82116001146107825790610772929161072782807f821a6365db69c1d64ad11e01534750e7fbbf9777b59caf69ff63371daaf73d72999a5f9161077757508160011b915f199060031b1c19161790565b90555b61076460405185878237808681015f815203902097610756604051978897606089526060890191610c51565b908682036020880152610b84565b918483036040860152610c51565b0390a2005b90508501358b61028d565b601f198216815f5260205f20905f5b8181106107f35750907f821a6365db69c1d64ad11e01534750e7fbbf9777b59caf69ff63371daaf73d7297988461077296959493106107da575b5050600182811b01905561072a565b8401355f19600385901b60f8161c1916905588806107cb565b858a013583556020998a019960019093019201610791565b90505f9291925260205f20905f915b8183106108335750509060206106a59282010189610698565b6020919350806001915483858c0101520191019091879261081a565b9050602092506106a594915060ff191682840152151560051b82010189610698565b6310bc162d60e21b5f5260045ffd5b6331aef0e560e01b5f5260045ffd5b34610126575f366003190112610126576108a7610dd8565b478015610906575f8080809360018060a01b038254165af16108c7610c8c565b50156108cf57005b60405162461bcd60e51b815260206004820152600f60248201526e15da5d1a191c985dc819985a5b1959608a1b6044820152606490fd5b60405162461bcd60e51b81526020600482015260136024820152724e6f7468696e6720746f20776974686472617760681b6044820152606490fd5b34610126576040366003190112610126576004356001600160401b03811161012657610971903690600401610b57565b6024356001600160a01b038116929190839003610126578215610a51576109988183610d9d565b5f818152600260205260409020549092906001600160a01b031615610880575f838152600260205260409020546001600160a01b03163303610871575f928352600260205260409283902080546001600160a01b03198116861790915592516001600160a01b03909316927fdf23d51f1260be237fa4088ead0c088c053d59be34359b0f2aadf45d8b7a5f3b919083828237808481015f815203902092610a4c604051928392602084526020840191610c51565b0390a4005b63a38ca3d960e01b5f5260045ffd5b34610126576020366003190112610126576004356001600160401b0381116101265761015d610a93913690600401610b57565b5f52600160205260405f20604051905f90805490610ab082610bf8565b8085529160018116908115610b305750600114610af0575b610aec84610ad881860382610c30565b604051918291602083526020830190610b84565b0390f35b5f90815260208120939250905b808210610b1657509091508101602001610ad882610ac8565b919260018160209254838588010152019101909291610afd565b60ff191660208087019190915292151560051b85019092019250610ad89150839050610ac8565b9181601f84011215610126578235916001600160401b038311610126576020838186019501011161012657565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b6040600319820112610126576004356001600160401b0381116101265781610bd291600401610b57565b92909291602435906001600160401b03821161012657610bf491600401610b57565b9091565b90600182811c92168015610c26575b6020831014610c1257565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610c07565b90601f801991011681019081106001600160401b0382111761045257604052565b908060209392818452848401375f828201840152601f01601f1916010190565b6001600160401b03811161045257601f01601f191660200190565b3d15610cb6573d90610c9d82610c71565b91610cab6040519384610c30565b82523d5f602084013e565b606090565b601f8211610cc857505050565b5f5260205f20906020601f840160051c83019310610d00575b601f0160051c01905b818110610cf5575050565b5f8155600101610cea565b9091508190610ce1565b508015610d975760018114610d8a5760028114610d7d5760038114610d705760048114610d635760058114610d5657600614610d4b5766354a6ba7a1800090565b666a94d74f43000090565b5067016345785d8a000090565b50670429d069189e000090565b50670de0b6b3a764000090565b506729a2241af62c000090565b50678ac7230489e8000090565b505f1990565b90610da781610c71565b90610db56040519283610c30565b8082526020820192368282011161012657815f9260209286378301015251902090565b5f546001600160a01b03163303610deb57565b63118cdaa760e01b5f523360045260245ffdfea2646970667358221220b56021b22a60b11a60f0d8c20f8f7e98abfea3b44fafc6901bd27949557489cb64736f6c634300081c0033

Deployed ByteCode

0x60806040526004361015610011575f80fd5b5f3560e01c806333e17c6014610a6057806337194d1e146109415780633ccfd60b1461088f57806343c2ee35146105fc578063524f3889146105b9578063715018a61461056257806373ff93a2146105455780638da5cb5b1461051e578063b4970b0f146101d4578063c822d7f014610181578063e18c3a061461012a5763f2fde38b1461009d575f80fd5b34610126576020366003190112610126576004356001600160a01b03811690819003610126576100cb610dd8565b8015610113575f80546001600160a01b03198116831782556001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a3005b631e4fbdf760e01b5f525f60045260245ffd5b5f80fd5b34610126576020366003190112610126576004356001600160401b0381116101265761015d610163913690600401610b57565b90610d9d565b5f526002602052602060018060a01b0360405f205416604051908152f35b34610126576020366003190112610126576004356001600160401b0381116101265761015d6101b4913690600401610b57565b5f526002602052602060018060a01b0360405f2054161515604051908152f35b6101dd36610ba8565b919092811561050f57821561050057602083036104f2576101fe8282610d9d565b5f818152600260205260409020546001600160a01b03166104e3576102238383610d0a565b908134106104d5575f81815260026020908152604080832080546001600160a01b03191633179055600190915290206001600160401b038611610452576102748661026e8354610bf8565b83610cbb565b5f86601f811160011461047157806102a0925f91610466575b508160011b915f199060031b1c19161790565b90555b5f52600360205260405f206001600160401b038411610452576102ca8461026e8354610bf8565b5f84601f81116001146103ef57806102f5925f916103e457508160011b915f199060031b1c19161790565b90555b6004545f1981146103d057600101600455803403903482116103d057340361037f575b507ffcd420f3c377ac516f77699a9c2a3d4109d0d28c17592854ca16517be96a77489161037a60405182848237808381015f81520390209461036a604051948594604086526040860191610c51565b9083820360208501523397610c51565b0390a3005b5f80808093335af161038f610c8c565b501561039b578461031b565b60405162461bcd60e51b815260206004820152600d60248201526c1499599d5b990819985a5b1959609a1b6044820152606490fd5b634e487b7160e01b5f52601160045260245ffd5b90508501358961028d565b50601f19851690825f528560205f20925f5b81811061043757501061041e575b5050600184811b0190556102f8565b8401355f19600387901b60f8161c19169055868061040f565b87840135855560019094019360209384019389935001610401565b634e487b7160e01b5f52604160045260245ffd5b90508901358a61028d565b50601f19871690825f528760205f20925f5b8b8282106104bb575050106104a2575b5050600186811b0190556102a3565b8801355f19600389901b60f8161c191690558780610493565b84013585556001909401936020938401938b935001610483565b62976f7560e21b5f5260045ffd5b630d706ecd60e21b5f5260045ffd5b6211911b60e81b5f5260045ffd5b636d91186360e01b5f5260045ffd5b632ef1310560e01b5f5260045ffd5b34610126575f366003190112610126575f546040516001600160a01b039091168152602090f35b34610126575f366003190112610126576020600454604051908152f35b34610126575f3660031901126101265761057a610dd8565b5f80546001600160a01b0319811682556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b34610126576020366003190112610126576004356001600160401b038111610126576105f46105ee6020923690600401610b57565b90610d0a565b604051908152f35b346101265761060a36610ba8565b929091831561050057602084036104f2576106258183610d9d565b5f818152600260205260409020549093906001600160a01b031615610880575f848152600260205260409020546001600160a01b0316330361087157835f52600160205260405f209360405194855f82549261068084610bf8565b808452936001811690811561084f575060011461080b575b506106a592500386610c30565b5f52600160205260405f20946001600160401b038111610452576106d3816106cd8854610bf8565b88610cbb565b5f95601f82116001146107825790610772929161072782807f821a6365db69c1d64ad11e01534750e7fbbf9777b59caf69ff63371daaf73d72999a5f9161077757508160011b915f199060031b1c19161790565b90555b61076460405185878237808681015f815203902097610756604051978897606089526060890191610c51565b908682036020880152610b84565b918483036040860152610c51565b0390a2005b90508501358b61028d565b601f198216815f5260205f20905f5b8181106107f35750907f821a6365db69c1d64ad11e01534750e7fbbf9777b59caf69ff63371daaf73d7297988461077296959493106107da575b5050600182811b01905561072a565b8401355f19600385901b60f8161c1916905588806107cb565b858a013583556020998a019960019093019201610791565b90505f9291925260205f20905f915b8183106108335750509060206106a59282010189610698565b6020919350806001915483858c0101520191019091879261081a565b9050602092506106a594915060ff191682840152151560051b82010189610698565b6310bc162d60e21b5f5260045ffd5b6331aef0e560e01b5f5260045ffd5b34610126575f366003190112610126576108a7610dd8565b478015610906575f8080809360018060a01b038254165af16108c7610c8c565b50156108cf57005b60405162461bcd60e51b815260206004820152600f60248201526e15da5d1a191c985dc819985a5b1959608a1b6044820152606490fd5b60405162461bcd60e51b81526020600482015260136024820152724e6f7468696e6720746f20776974686472617760681b6044820152606490fd5b34610126576040366003190112610126576004356001600160401b03811161012657610971903690600401610b57565b6024356001600160a01b038116929190839003610126578215610a51576109988183610d9d565b5f818152600260205260409020549092906001600160a01b031615610880575f838152600260205260409020546001600160a01b03163303610871575f928352600260205260409283902080546001600160a01b03198116861790915592516001600160a01b03909316927fdf23d51f1260be237fa4088ead0c088c053d59be34359b0f2aadf45d8b7a5f3b919083828237808481015f815203902092610a4c604051928392602084526020840191610c51565b0390a4005b63a38ca3d960e01b5f5260045ffd5b34610126576020366003190112610126576004356001600160401b0381116101265761015d610a93913690600401610b57565b5f52600160205260405f20604051905f90805490610ab082610bf8565b8085529160018116908115610b305750600114610af0575b610aec84610ad881860382610c30565b604051918291602083526020830190610b84565b0390f35b5f90815260208120939250905b808210610b1657509091508101602001610ad882610ac8565b919260018160209254838588010152019101909291610afd565b60ff191660208087019190915292151560051b85019092019250610ad89150839050610ac8565b9181601f84011215610126578235916001600160401b038311610126576020838186019501011161012657565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b6040600319820112610126576004356001600160401b0381116101265781610bd291600401610b57565b92909291602435906001600160401b03821161012657610bf491600401610b57565b9091565b90600182811c92168015610c26575b6020831014610c1257565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610c07565b90601f801991011681019081106001600160401b0382111761045257604052565b908060209392818452848401375f828201840152601f01601f1916010190565b6001600160401b03811161045257601f01601f191660200190565b3d15610cb6573d90610c9d82610c71565b91610cab6040519384610c30565b82523d5f602084013e565b606090565b601f8211610cc857505050565b5f5260205f20906020601f840160051c83019310610d00575b601f0160051c01905b818110610cf5575050565b5f8155600101610cea565b9091508190610ce1565b508015610d975760018114610d8a5760028114610d7d5760038114610d705760048114610d635760058114610d5657600614610d4b5766354a6ba7a1800090565b666a94d74f43000090565b5067016345785d8a000090565b50670429d069189e000090565b50670de0b6b3a764000090565b506729a2241af62c000090565b50678ac7230489e8000090565b505f1990565b90610da781610c71565b90610db56040519283610c30565b8082526020820192368282011161012657815f9260209286378301015251902090565b5f546001600160a01b03163303610deb57565b63118cdaa760e01b5f523360045260245ffdfea2646970667358221220b56021b22a60b11a60f0d8c20f8f7e98abfea3b44fafc6901bd27949557489cb64736f6c634300081c0033