Skip to content

Add UpgradeableRegistrarController #123

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 48 commits into from
May 28, 2025
Merged

Conversation

stevieraykatz
Copy link
Collaborator

@stevieraykatz stevieraykatz commented Apr 16, 2025

An Upgradeable version of our RegistrarController. Includes the following changes from our existing contract:

  • All state moved into EIP-7201 compliant slots
  • "Launch" premium logic removed
  • Support for ENS L2ReverseRegistrar added for reverse record setting

@cb-heimdall
Copy link
Collaborator

cb-heimdall commented Apr 16, 2025

✅ Heimdall Review Status

Requirement Status More Info
Reviews 1/1
Denominator calculation
Show calculation
1 if user is bot 0
1 if user is external 0
2 if repo is sensitive 0
From .codeflow.yml 1
Additional review requirements
Show calculation
Max 0
0
From CODEOWNERS 0
Global minimum 0
Max 1
1
1 if commit is unverified 0
Sum 1

Comment on lines 576 to 586
/// @notice Getter for fetching token expiry.
///
/// @dev If the token returns a `0` expiry time, it hasn't been registered before.
///
/// @param tokenId The ID of the token to check for expiry.
///
/// @return expires Returns the expiry + GRACE_PERIOD for previously registered names, else 0.
function _getExpiry(uint256 tokenId) internal view returns (uint256 expires) {
expires = _getURCStorage().base.nameExpires(tokenId);
return expires == 0 ? 0 : expires + GRACE_PERIOD;
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method has changed from RegistrarController to eliminate the launch auction logic.

amiecorso
amiecorso previously approved these changes May 27, 2025
Copy link

@amiecorso amiecorso left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really just a few nits! Definitely pieces of this system at large I still don't understand but getting there.

/// @param newPaymentReceiver The address of the new payment receiver.
event PaymentReceiverUpdated(address newPaymentReceiver);

/// @notice Emitted when the price oracle is updated.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: the "price oracle" is also referred to as the "pricing oracle" and the "prices oracle" at various places in this file, might be good to standardize

view
returns (uint256 price)
{
uint256 discount = _getURCStorage().discounts[discountKey].discount;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just an observation but seems interesting to me that discounts are fixed and independent of the registerPrice for the name v.s. a percentage discounted etc.

ilikesymmetry
ilikesymmetry previously approved these changes May 27, 2025
Copy link
Collaborator

@ilikesymmetry ilikesymmetry left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just finished a full pass on source code. You should probably ignore most of my comments that ask for name changes that impact src non-trivially. Didn't have much time to clean up or sort my thinking sorry, but thought the reactions of someone onboarding to the codebase would still be helpful!

Will review tests later, but think we're good to proceed for now :)

Comment on lines 8 to 11
/// @param owner The address to set as the owner of the reverse record in ENS.
///
/// @return The ENS node hash of the base-specific reverse record.
function claim(address owner) external returns (bytes32);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really understand this function's purpose from the comments. How is it intended to be used compared to setNameForAddrWithSignature?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

msg.sender has to be the address that's getting a reverse record set for the specified owner. It's used by contracts that want to claim their name for reverse record setting (where they can delegate management of their reverse record back to owner).

///
/// @param request The `RegisterRequest` struct containing the details for the registration.
function _register(RegisterRequest calldata request) internal {
bytes32 labelhash = keccak256(bytes(request.name));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: seen this inconsistently called label and labelhash. If labelhash, would think labelHash follows convention more?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ugh, i agree but fixing this changes events and i'd rather not break things and expand the scope... leaving as is and acknowledging that the nomenclature is confusing.

/// @param label The keccak256 namehash for the specified name.
/// @param data The abi encoded calldata records that will be used in the multicallable resolver.
function _setRecords(address resolverAddress, bytes32 label, bytes[] calldata data) internal {
bytes32 nodehash = keccak256(abi.encodePacked(_getURCStorage().rootNode, label));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: nodeHash?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also find it interesting that the label is after the parent node. Was the base.eth node also calculated by having the "eth" node before the "base" node?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah the order of hashing is a little confusing: https://docs.ens.domains/resolution/names/#algorithm

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the spelling of nodehash is consistent with other uses

/// @dev `multicallWithNodeCheck` ensures that each record being set is for the specified `label`.
///
/// @param resolverAddress The address of the resolver to set records on.
/// @param label The keccak256 namehash for the specified name.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: "namehash" intuits immediately while "label" does not from a naming perspective

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Though i agree, this is actually incorrect. A namehash == nodehash in ENS parlance. Fixing

uint256[] memory cointypes,
bytes memory signature
) internal {
_getURCStorage().reverseRegistrar.setNameForAddrWithSignature(msg.sender, expiry, name, cointypes, signature);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find it a bit odd that owner arg doesn't seem be used here? What is the significants of using msg.sender here?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also don't notice resolver being used either

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Vestigial from old Registrar Controller and unused. Removing them from the helper signature.

They're no longer needed because:

  • owner is now implicitly tied to the signature data
  • resolver isn't set because the records are no longer stored in a generic resolver but directly on the canonical L2ReverseResolver.

@cb-heimdall
Copy link
Collaborator

Review Error for ilikesymmetry @ 2025-05-27 19:49:39 UTC
User failed mfa authentication, see go/mfa-help

@stevieraykatz stevieraykatz dismissed stale reviews from ilikesymmetry and amiecorso via d8cb250 May 27, 2025 20:40
ilikesymmetry
ilikesymmetry previously approved these changes May 28, 2025
@cb-heimdall
Copy link
Collaborator

Review Error for ilikesymmetry @ 2025-05-28 01:00:33 UTC
User failed mfa authentication, see go/mfa-help

@ilikesymmetry ilikesymmetry self-requested a review May 28, 2025 15:38
@stevieraykatz stevieraykatz merged commit 2418f4a into main May 28, 2025
7 checks passed
@stevieraykatz stevieraykatz deleted the upgradeable-registrar branch May 28, 2025 15:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants