I’ve had a new idea for contract naming that I’d like to discuss. Some prior ideas were discussed in this github PR. New idea discussed here and expanded below:
interface IContractName {
function contractName() external view returns (string memory);
}
On L1, a contract can name itself by implementing IContractName. The detection method can be ERC-165 or a blind call with a valid response. The addr.reverse resolver can implement this check. This dodges the ownership requirement.
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 stored into the registrar), the only option currently is to implement owner().
However, a similar mechanism like L1 would work: there can be a function on the registrar that anyone can call, and if the address supports IContractName, it copies that name accordingly.
In both situations, the requirement would be the response must be onchain.
I believe this is significantly simpler than ReverseClaimer (current solution) and ReverseNamer (prior suggestion).
Example usage:
contract MyContract {
string public contractName = "mycontract.eth";
}
// if deployed on L1
// 1. setAddr(`mycontract.eth`, 60, <MyContract>);
// 2. named!
// if deployed on L2
// 1. setAddr(`mycontract.eth`, <chain>, <MyContract>);
// 2a. L2ReverseRegistrar.syncContractName(<MyContract>); // called by anyone
// 2b. L2ReverseRegistrar.syncContractName(); // called by contract
// 3. named!
An alternative option:
contract MyContract {
address public contractNamer = 0x51050ec063d393217B436747617aD1C2285Aeeee;
}
As Ownable is often not the right construction. In ENSv2, many contracts use EAC which doesn’t have a single owner, however typically there is someone who would be responsible for naming, eg. DAO names core ENS contracts.
There’s also a more generalized contractNamer()-like interface:
interface IContractNameable {
function isContractNamer(address account) external view returns (bool);
}
The advantage being you could have an EAC role like ROLE_NAMER and implement the following:
contract MyContract is EnhancedAccessContract, IContractNameable {
function isContractNamer(address account) external view returns (bool) {
return hasRootRoles(ROLE_NAMER, account);
}
}
Ownable would use:
contract MyContract is Ownable, IContractNameable {
function isContractNamer(address account) external view returns (bool) {
return account == owner();
}
}
tl;dr
- Reduce complexity so it’s simple to name your contract.
- Modify
addr.reverseresolver to ask mainnet contracts for their name directly. - Add alternative to
OwnableforL2ReverseRegistrar.