ETH Price: $2,528.36 (+0.29%)

Transaction Decoder

Block:
16716502 at Feb-27-2023 02:16:47 AM +UTC
Transaction Fee:
0.002476770454222796 ETH $6.26
Gas Used:
123,113 Gas / 20.117862892 Gwei

Account State Difference:

  Address   Before After State Difference Code
0x283Af0B2...A627EB7F5
(ENS: Old ETH Registrar Controller)
0xC30eAF1D...1aA201CAc
0.032615767522862124 Eth
Nonce: 545
0.030138997068639328 Eth
Nonce: 546
0.002476770454222796
(Fee Recipient: 0xDe...762)
30.564543439861126564 Eth30.564604996361126564 Eth0.0000615565

Execution Trace

0x000000000000509081d6fcd3ee63e791ad1db763.8813034e( )
  • ETHRegistrarController.commit( commitment=4A7BDF9D13BD5BB3BAB277FA5A2469DF72E10F9DEB6747BFCA82210D8B2956CD )
  • ETHRegistrarController.commit( commitment=90A81709C238BFB71AF179725F0FA1A409EE0A61E115A5C39F0A70B7998119E9 )
  • ETHRegistrarController.commit( commitment=787B582A62C4A73A0F1793C6B519662E7DF781D99459723FCD800EBA260C0964 )
  • ETHRegistrarController.commit( commitment=910691FE4E0BABE88F796267A27392879B1C9CE0D93576B28FA426CE49B19EA8 )
    // File: @ensdomains/ethregistrar/contracts/PriceOracle.sol
    
    pragma solidity >=0.4.24;
    
    interface PriceOracle {
        /**
         * @dev Returns the price to register or renew a name.
         * @param name The name being registered or renewed.
         * @param expires When the name presently expires (0 if this is a new registration).
         * @param duration How long the name is being registered or extended for, in seconds.
         * @return The price of this renewal or registration, in wei.
         */
        function price(string calldata name, uint expires, uint duration) external view returns(uint);
    }
    
    // File: @ensdomains/ens/contracts/ENS.sol
    
    pragma solidity >=0.4.24;
    
    interface ENS {
    
        // Logged when the owner of a node assigns a new owner to a subnode.
        event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);
    
        // Logged when the owner of a node transfers ownership to a new account.
        event Transfer(bytes32 indexed node, address owner);
    
        // Logged when the resolver for a node changes.
        event NewResolver(bytes32 indexed node, address resolver);
    
        // Logged when the TTL of a node changes
        event NewTTL(bytes32 indexed node, uint64 ttl);
    
        // Logged when an operator is added or removed.
        event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
    
        function setRecord(bytes32 node, address owner, address resolver, uint64 ttl) external;
        function setSubnodeRecord(bytes32 node, bytes32 label, address owner, address resolver, uint64 ttl) external;
        function setSubnodeOwner(bytes32 node, bytes32 label, address owner) external returns(bytes32);
        function setResolver(bytes32 node, address resolver) external;
        function setOwner(bytes32 node, address owner) external;
        function setTTL(bytes32 node, uint64 ttl) external;
        function setApprovalForAll(address operator, bool approved) external;
        function owner(bytes32 node) external view returns (address);
        function resolver(bytes32 node) external view returns (address);
        function ttl(bytes32 node) external view returns (uint64);
        function recordExists(bytes32 node) external view returns (bool);
        function isApprovedForAll(address owner, address operator) external view returns (bool);
    }
    
    // File: openzeppelin-solidity/contracts/introspection/IERC165.sol
    
    pragma solidity ^0.5.0;
    
    /**
     * @title IERC165
     * @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md
     */
    interface IERC165 {
        /**
         * @notice Query if a contract implements an interface
         * @param interfaceId The interface identifier, as specified in ERC-165
         * @dev Interface identification is specified in ERC-165. This function
         * uses less than 30,000 gas.
         */
        function supportsInterface(bytes4 interfaceId) external view returns (bool);
    }
    
    // File: openzeppelin-solidity/contracts/token/ERC721/IERC721.sol
    
    pragma solidity ^0.5.0;
    
    
    /**
     * @title ERC721 Non-Fungible Token Standard basic interface
     * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
     */
    contract IERC721 is IERC165 {
        event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
        event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
        event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
    
        function balanceOf(address owner) public view returns (uint256 balance);
        function ownerOf(uint256 tokenId) public view returns (address owner);
    
        function approve(address to, uint256 tokenId) public;
        function getApproved(uint256 tokenId) public view returns (address operator);
    
        function setApprovalForAll(address operator, bool _approved) public;
        function isApprovedForAll(address owner, address operator) public view returns (bool);
    
        function transferFrom(address from, address to, uint256 tokenId) public;
        function safeTransferFrom(address from, address to, uint256 tokenId) public;
    
        function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public;
    }
    
    // File: openzeppelin-solidity/contracts/ownership/Ownable.sol
    
    pragma solidity ^0.5.0;
    
    /**
     * @title Ownable
     * @dev The Ownable contract has an owner address, and provides basic authorization control
     * functions, this simplifies the implementation of "user permissions".
     */
    contract Ownable {
        address private _owner;
    
        event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
    
        /**
         * @dev The Ownable constructor sets the original `owner` of the contract to the sender
         * account.
         */
        constructor () internal {
            _owner = msg.sender;
            emit OwnershipTransferred(address(0), _owner);
        }
    
        /**
         * @return the address of the owner.
         */
        function owner() public view returns (address) {
            return _owner;
        }
    
        /**
         * @dev Throws if called by any account other than the owner.
         */
        modifier onlyOwner() {
            require(isOwner());
            _;
        }
    
        /**
         * @return true if `msg.sender` is the owner of the contract.
         */
        function isOwner() public view returns (bool) {
            return msg.sender == _owner;
        }
    
        /**
         * @dev Allows the current owner to relinquish control of the contract.
         * @notice Renouncing to ownership will leave the contract without an owner.
         * It will not be possible to call the functions with the `onlyOwner`
         * modifier anymore.
         */
        function renounceOwnership() public onlyOwner {
            emit OwnershipTransferred(_owner, address(0));
            _owner = address(0);
        }
    
        /**
         * @dev Allows the current owner to transfer control of the contract to a newOwner.
         * @param newOwner The address to transfer ownership to.
         */
        function transferOwnership(address newOwner) public onlyOwner {
            _transferOwnership(newOwner);
        }
    
        /**
         * @dev Transfers control of the contract to a newOwner.
         * @param newOwner The address to transfer ownership to.
         */
        function _transferOwnership(address newOwner) internal {
            require(newOwner != address(0));
            emit OwnershipTransferred(_owner, newOwner);
            _owner = newOwner;
        }
    }
    
    // File: @ensdomains/ethregistrar/contracts/BaseRegistrar.sol
    
    pragma solidity >=0.4.24;
    
    
    
    
    contract BaseRegistrar is IERC721, Ownable {
        uint constant public GRACE_PERIOD = 90 days;
    
        event ControllerAdded(address indexed controller);
        event ControllerRemoved(address indexed controller);
        event NameMigrated(uint256 indexed id, address indexed owner, uint expires);
        event NameRegistered(uint256 indexed id, address indexed owner, uint expires);
        event NameRenewed(uint256 indexed id, uint expires);
    
        // The ENS registry
        ENS public ens;
    
        // The namehash of the TLD this registrar owns (eg, .eth)
        bytes32 public baseNode;
    
        // A map of addresses that are authorised to register and renew names.
        mapping(address=>bool) public controllers;
    
        // Authorises a controller, who can register and renew domains.
        function addController(address controller) external;
    
        // Revoke controller permission for an address.
        function removeController(address controller) external;
    
        // Set the resolver for the TLD this registrar manages.
        function setResolver(address resolver) external;
    
        // Returns the expiration timestamp of the specified label hash.
        function nameExpires(uint256 id) external view returns(uint);
    
        // Returns true iff the specified name is available for registration.
        function available(uint256 id) public view returns(bool);
    
        /**
         * @dev Register a name.
         */
        function register(uint256 id, address owner, uint duration) external returns(uint);
    
        function renew(uint256 id, uint duration) external returns(uint);
    
        /**
         * @dev Reclaim ownership of a name in ENS, if you own it in the registrar.
         */
        function reclaim(uint256 id, address owner) external;
    }
    
    // File: @ensdomains/ethregistrar/contracts/StringUtils.sol
    
    pragma solidity >=0.4.24;
    
    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 (uint) {
            uint len;
            uint i = 0;
            uint bytelength = bytes(s).length;
            for(len = 0; i < bytelength; len++) {
                byte 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: @ensdomains/resolver/contracts/Resolver.sol
    
    pragma solidity >=0.4.25;
    
    /**
     * A generic resolver interface which includes all the functions including the ones deprecated
     */
    interface Resolver{
        event AddrChanged(bytes32 indexed node, address a);
        event AddressChanged(bytes32 indexed node, uint coinType, bytes newAddress);
        event NameChanged(bytes32 indexed node, string name);
        event ABIChanged(bytes32 indexed node, uint256 indexed contentType);
        event PubkeyChanged(bytes32 indexed node, bytes32 x, bytes32 y);
        event TextChanged(bytes32 indexed node, string indexed indexedKey, string key);
        event ContenthashChanged(bytes32 indexed node, bytes hash);
        /* Deprecated events */
        event ContentChanged(bytes32 indexed node, bytes32 hash);
    
        function ABI(bytes32 node, uint256 contentTypes) external view returns (uint256, bytes memory);
        function addr(bytes32 node) external view returns (address);
        function addr(bytes32 node, uint coinType) external view returns(bytes memory);
        function contenthash(bytes32 node) external view returns (bytes memory);
        function dnsrr(bytes32 node) external view returns (bytes memory);
        function name(bytes32 node) external view returns (string memory);
        function pubkey(bytes32 node) external view returns (bytes32 x, bytes32 y);
        function text(bytes32 node, string calldata key) external view returns (string memory);
        function interfaceImplementer(bytes32 node, bytes4 interfaceID) external view returns (address);
    
        function setABI(bytes32 node, uint256 contentType, bytes calldata data) external;
        function setAddr(bytes32 node, address addr) external;
        function setAddr(bytes32 node, uint coinType, bytes calldata a) external;
        function setContenthash(bytes32 node, bytes calldata hash) external;
        function setDnsrr(bytes32 node, bytes calldata data) external;
        function setName(bytes32 node, string calldata _name) external;
        function setPubkey(bytes32 node, bytes32 x, bytes32 y) external;
        function setText(bytes32 node, string calldata key, string calldata value) external;
        function setInterface(bytes32 node, bytes4 interfaceID, address implementer) external;
    
        function supportsInterface(bytes4 interfaceID) external pure returns (bool);
    
        /* Deprecated functions */
        function content(bytes32 node) external view returns (bytes32);
        function multihash(bytes32 node) external view returns (bytes memory);
        function setContent(bytes32 node, bytes32 hash) external;
        function setMultihash(bytes32 node, bytes calldata hash) external;
    }
    
    // File: @ensdomains/ethregistrar/contracts/ETHRegistrarController.sol
    
    pragma solidity ^0.5.0;
    
    
    
    
    
    
    /**
     * @dev A registrar controller for registering and renewing names at fixed cost.
     */
    contract ETHRegistrarController is Ownable {
        using StringUtils for *;
    
        uint constant public MIN_REGISTRATION_DURATION = 28 days;
    
        bytes4 constant private INTERFACE_META_ID = bytes4(keccak256("supportsInterface(bytes4)"));
        bytes4 constant private COMMITMENT_CONTROLLER_ID = bytes4(
            keccak256("rentPrice(string,uint256)") ^
            keccak256("available(string)") ^
            keccak256("makeCommitment(string,address,bytes32)") ^
            keccak256("commit(bytes32)") ^
            keccak256("register(string,address,uint256,bytes32)") ^
            keccak256("renew(string,uint256)")
        );
    
        bytes4 constant private COMMITMENT_WITH_CONFIG_CONTROLLER_ID = bytes4(
            keccak256("registerWithConfig(string,address,uint256,bytes32,address,address)") ^
            keccak256("makeCommitmentWithConfig(string,address,bytes32,address,address)")
        );
    
        BaseRegistrar base;
        PriceOracle prices;
        uint public minCommitmentAge;
        uint public maxCommitmentAge;
    
        mapping(bytes32=>uint) public commitments;
    
        event NameRegistered(string name, bytes32 indexed label, address indexed owner, uint cost, uint expires);
        event NameRenewed(string name, bytes32 indexed label, uint cost, uint expires);
        event NewPriceOracle(address indexed oracle);
    
        constructor(BaseRegistrar _base, PriceOracle _prices, uint _minCommitmentAge, uint _maxCommitmentAge) public {
            require(_maxCommitmentAge > _minCommitmentAge);
    
            base = _base;
            prices = _prices;
            minCommitmentAge = _minCommitmentAge;
            maxCommitmentAge = _maxCommitmentAge;
        }
    
        function rentPrice(string memory name, uint duration) view public returns(uint) {
            bytes32 hash = keccak256(bytes(name));
            return prices.price(name, base.nameExpires(uint256(hash)), duration);
        }
    
        function valid(string memory name) public pure returns(bool) {
            return name.strlen() >= 3;
        }
    
        function available(string memory name) public view returns(bool) {
            bytes32 label = keccak256(bytes(name));
            return valid(name) && base.available(uint256(label));
        }
    
        function makeCommitment(string memory name, address owner, bytes32 secret) pure public returns(bytes32) {
            return makeCommitmentWithConfig(name, owner, secret, address(0), address(0));
        }
    
        function makeCommitmentWithConfig(string memory name, address owner, bytes32 secret, address resolver, address addr) pure public returns(bytes32) {
            bytes32 label = keccak256(bytes(name));
            if (resolver == address(0) && addr == address(0)) {
                return keccak256(abi.encodePacked(label, owner, secret));
            }
            require(resolver != address(0));
            return keccak256(abi.encodePacked(label, owner, resolver, addr, secret));
        }
    
        function commit(bytes32 commitment) public {
            require(commitments[commitment] + maxCommitmentAge < now);
            commitments[commitment] = now;
        }
    
        function register(string calldata name, address owner, uint duration, bytes32 secret) external payable {
          registerWithConfig(name, owner, duration, secret, address(0), address(0));
        }
    
        function registerWithConfig(string memory name, address owner, uint duration, bytes32 secret, address resolver, address addr) public payable {
            bytes32 commitment = makeCommitmentWithConfig(name, owner, secret, resolver, addr);
            uint cost = _consumeCommitment(name, duration, commitment);
    
            bytes32 label = keccak256(bytes(name));
            uint256 tokenId = uint256(label);
    
            uint expires;
            if(resolver != address(0)) {
                // Set this contract as the (temporary) owner, giving it
                // permission to set up the resolver.
                expires = base.register(tokenId, address(this), duration);
    
                // The nodehash of this label
                bytes32 nodehash = keccak256(abi.encodePacked(base.baseNode(), label));
    
                // Set the resolver
                base.ens().setResolver(nodehash, resolver);
    
                // Configure the resolver
                if (addr != address(0)) {
                    Resolver(resolver).setAddr(nodehash, addr);
                }
    
                // Now transfer full ownership to the expeceted owner
                base.reclaim(tokenId, owner);
                base.transferFrom(address(this), owner, tokenId);
            } else {
                require(addr == address(0));
                expires = base.register(tokenId, owner, duration);
            }
    
            emit NameRegistered(name, label, owner, cost, expires);
    
            // Refund any extra payment
            if(msg.value > cost) {
                msg.sender.transfer(msg.value - cost);
            }
        }
    
        function renew(string calldata name, uint duration) external payable {
            uint cost = rentPrice(name, duration);
            require(msg.value >= cost);
    
            bytes32 label = keccak256(bytes(name));
            uint expires = base.renew(uint256(label), duration);
    
            if(msg.value > cost) {
                msg.sender.transfer(msg.value - cost);
            }
    
            emit NameRenewed(name, label, cost, expires);
        }
    
        function setPriceOracle(PriceOracle _prices) public onlyOwner {
            prices = _prices;
            emit NewPriceOracle(address(prices));
        }
    
        function setCommitmentAges(uint _minCommitmentAge, uint _maxCommitmentAge) public onlyOwner {
            minCommitmentAge = _minCommitmentAge;
            maxCommitmentAge = _maxCommitmentAge;
        }
    
        function withdraw() public onlyOwner {
            msg.sender.transfer(address(this).balance);
        }
    
        function supportsInterface(bytes4 interfaceID) external pure returns (bool) {
            return interfaceID == INTERFACE_META_ID ||
                   interfaceID == COMMITMENT_CONTROLLER_ID ||
                   interfaceID == COMMITMENT_WITH_CONFIG_CONTROLLER_ID;
        }
    
        function _consumeCommitment(string memory name, uint duration, bytes32 commitment) internal returns (uint256) {
            // Require a valid commitment
            require(commitments[commitment] + minCommitmentAge <= now);
    
            // If the commitment is too old, or the name is registered, stop
            require(commitments[commitment] + maxCommitmentAge > now);
            require(available(name));
    
            delete(commitments[commitment]);
    
            uint cost = rentPrice(name, duration);
            require(duration >= MIN_REGISTRATION_DURATION);
            require(msg.value >= cost);
    
            return cost;
        }
    }