Add ENSIP: Contract Self-Naming#60
Conversation
This ENSIP enables contracts to declare their own reverse names using ERC-8049 metadata with Optional Diamond Storage extension. Contracts can self-declare their ENS name during deployment, and any account can then trustlessly verify and permissionlessly register the contract's reverse name in the registrar. Key features: - Contracts declare reverse names via ERC-8049 metadata at key 'eth.ens.reverse-name' - Predictable storage locations enable trustless verification - Permissionless registration removes burden from contract deployers - Compatible with ENSIP-19 - Includes verified storage slot calculations
- Note that contract owner may not always exist - Mention alternative of making custom external call in constructor
- Change 'ABI-encoded' to 'stored as bytes' for value format (correct terminology) - Clarify single-slot verification applies to names under 32 characters - Update rationale to emphasize admin-free contracts use case
This updates the Contract Self-Naming ENSIP to remove the ERC-8049 dependency and instead use
an ERC-8042 diamond storage slot keyed by "eth.ens.reverse-name".
Key changes:
- Replace the ERC-8049 Optional Diamond Storage metadata mapping approach with direct ERC-8042
storage location addressing.
- Define the storage location as keccak256("eth.ens.reverse-name"), matching ERC-8042’s formula
(erc8042(id) = keccak256(id)).
- Specify that the value stored at this slot is a bytes32 namehash (rather than a UTF-8 bytes
string), keeping the declaration single-slot and efficient to verify.
- Update the Solidity example to the canonical diamond-storage struct pattern:
- STORAGE_POSITION constant
- getStorage() that assigns s.slot via assembly
- @Custom:storage-location erc8042:eth.ens.reverse-name annotation
- set ReverseNameStorage.reverseNameHash during deployment
- Update abstract/motivation/rationale/backwards compatibility wording and references to reflect
the simplified ERC-8042-only approach.
- Add raffy.eth as a contributor.
Update the example contract in the Contract Self-Naming ENSIP to explicitly use namehash("mycontract.eth").
|
|
||
| ## Abstract | ||
|
|
||
| This ENSIP extends ENSIP-19 to enable contracts to declare their own reverse names using ERC-8042 Diamond Storage. By storing a namehash of the reverse name in a known storage location, contracts can self-declare their ENS name. Any account can then register this name using the reverse registrar on L1, or using an L2 reverse registrar. This enables trustless, permissionless reverse name registration for contracts without requiring the contract deployer to perform additional registration steps. |
There was a problem hiding this comment.
You mean the namehash of the primary name?
"Any account can then register this name using the reverse registrar on L1, or using an L2 reverse registrar."
This spec doesn't outline how..?
|
Wouldn't a simpler implementation be to define an interface with a predicate function that allows the contract to explicitly accept or reject a primary name? Also, presumably the idea here is to update the reverse registrar to support checking this and setting the name accordingly, but this isn't mentioned anywhere. |
By predicate function, do you mean something like With a named storage slot using ERC‑8042 Diamond Storage, the storage value itself acts as the verification. If the Example: constructor() {
// Declare ENS reverse name using ERC-8042 Diamond Storage
// Slot: keccak256("eth.ens.reverse-name")
// Value: namehash("mycontract.eth")
// This allows any account to permissionlessly register the reverse name
assembly {
sstore(
0x09ded414ae6c0ce389342caf0619071d5be1687a6f7314e74bcc7cfa1a0df4bf,
0x6ff093714e95f3f123db7d14a81db07d48e7e0f7ca7ef35ca446facd9d5e7c1c
)
}
}
I agree, I can work on that and document it once the self-naming mechanism is finalized. |
|
How about: On L1, a contract can name itself by implementing On L2 (or any contract that interfaces with the crosschain reverse registrars), since we want names stored in one contract for read simplicity (so the name needs copied into the registrar), the only option currently is to implement However, a similar mechanism like above would work: there can be a function on the registrar that anyone can call, and if the address supports In both situations, the requirement would be the Instead of ERC-165, it could just be a blind call with a non-empty string response. It would be up to the contract to check if |
Except it requires referencing ERC-8042, which is large and overengineered.
Nor does my suggested alternative require this
20k gas - while a simple constant-returning function uses much less
Which is a cost, rather than a benefit, since you may want to change the primary name |
We can remove the dependency on ERC-8042 and simply have the storage location use the same scheme, which I think is simpler than ERC-7201?
I agree.
Right, if it is a constant, I agree.
How does this affect whether it can be updated or not? If we use a function, then that friction is required for every upgrade, whether or not the developer wants that friction, because the developer needs to ensure that the function call persists across upgrades. I also think this may be a key part of the design:
We might also decide in the future to allow L2 reverse names to be registered on L1, in which case we could use an inclusion proof to verify the contract name. Another idea would be to just do both methods. If the goal is to make it as easy for contract developers as possible to set their reverse name, then we could offer both methods as options, allowing for developers to decide what works best for them. |
How is leaving a piece of code unmodified 'friction'? |
Because it's necessary to continue to manage the interface, such as isReverseName(bytes32 namehash) returns (bool), across multiple contract upgrades, whereas setting the named storage value in the constructor can be done only once and persists across upgrades. My original intention for this proposal was to try to make it as easy as possible for a contract to name itself. I couldn't think of anything easier than setting a storage value. |
This is a real stretch. I think having invisible state that isn't encompassed by the current version of the source is much more of a maintenance and transparency issue than a 3-line function you simply leave alone. |
I think that most implementers would like the value to be mutable, and therefore would create a setter function.
I am happy to move forward with either design, or both. If I change this PR to just support |
Summary
This PR adds a new ENSIP that enables contracts to declare their own reverse names using ERC-8042 Diamond Storage. By storing a namehash in a predictable ERC-8042 storage slot keyed by
"eth.ens.reverse-name", contracts can self-declare their ENS name during deployment, enabling trustless and permissionless reverse name registration.Key Features
Specification Details
"eth.ens.reverse-name"keccak256("eth.ens.reverse-name")(ERC-8042)bytes32namehash of the ENS name (e.g.,namehash("mycontract.eth"))