Transaction Hash:
Block:
15197505 at Jul-23-2022 07:06:51 AM +UTC
Transaction Fee:
0.000415145570186906 ETH
$0.78
Gas Used:
46,267 Gas / 8.972822318 Gwei
Account State Difference:
Address | Before | After | State Difference | ||
---|---|---|---|---|---|
0x283Af0B2...A627EB7F5 | (ENS: Old ETH Registrar Controller) | ||||
0x829BD824...93333A830
Miner
| (F2Pool Old) | 5,674.730105066473308439 Eth | 5,674.730174466973308439 Eth | 0.0000694005 | |
0xBB07234B...f3f085644 |
0.46816579175946622 Eth
Nonce: 17
|
0.467750646189279314 Eth
Nonce: 18
| 0.000415145570186906 |
Execution Trace
ETHRegistrarController.commit( commitment=BC2210DDA127B194B4A54FA8ECDBB1870F9E96C77FB948DAE8B704AFCC96DA94 )
// 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; } }