-
Notifications
You must be signed in to change notification settings - Fork 0
Managed ENS Registrar and Resolver #1
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
Open
shazow
wants to merge
52
commits into
main
Choose a base branch
from
wip
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
52 commits
Select commit
Hold shift + click to select a range
82ae188
Add foundry flake
shazow d819cf1
forge init
shazow fce2b28
Makefile
shazow 0d13f0f
wip: Replace sample code with some skeleton contracts
shazow 4940796
forge install: solmate
shazow 539fc64
wip: ManagedENSResolver
shazow 601ed7d
WIP: ManagedRegistrar
shazow 8ce2b2b
string subdomains -> bytes32
shazow 9e192db
WIP: ManagedResolver, ManagedENSResolver
shazow e2c947b
Resolver: Comply with EIP-137 spec
shazow cebefe6
Registrar: Remove Archive, lets do it offchain instead
shazow bd6922e
builds!
shazow 5ec2b1e
forge install: ens-contracts
shazow f4a611b
tests: Add basic ManagedRegistrar tests
shazow fcff63e
tests: testOwner, testSet for invalid addr
shazow 97b69ea
WIP: tests: ManagedENSResolver sketch but BytesUtils is not working yet
shazow 4b8b982
tests: Use our own namehash implementation 🙃
shazow 5e149f1
tests: Reformat, add Multiset tests
shazow 066e05a
tests: Added two tier helper
shazow 69eef63
tests: Add a subdomain namehash function, may need it later
shazow 0212621
test: Pull out helpers
shazow 61718a0
ManagedENSResolver: Remove Owned
shazow a2f5f8c
script: Add basic deploy script
shazow d0052a6
deploy, deploy-forked
shazow 7b81f7a
test: Add generative tests for benchmarking
shazow 93ab89f
WIP: Forked chain override for resolver, impersonate not working
shazow e19febf
script: Add override helper
shazow 656a72c
script/override.sh: Add example call for setSubnodeRecord
shazow 52034dd
src/ManagedENSResolver.sol: Added resolver and resolve interfaces, wo…
shazow 5128d74
WIP: Started rewriting ManagedRegistrar to use ens.setSubnodeOwner(...)
shazow f58b7d3
script/override.sh: Add alternative register method
shazow 5c90ac4
WIP: Changing Resolver to wrap Registrar.set with subnode setting
shazow dd72554
WIP: E2E test using a forked ENS instance, almost passing
shazow ea7c9c9
test: ENSFork passes
shazow b4f25a0
ManagedRegistrar: Allow both owner and adminSetter, add tests
shazow 4f48b1c
script/override.sh: Take registrar for overriding
shazow 3ff16cb
src: Split a base Resolver from ManagedENSResolver
shazow f367289
src: Add ChildResolver which proxies a parent IFullResolver for addit…
shazow 57be9df
src: Add ManagedRegistrarWithReverse impl, INameResolver impl for res…
shazow 58de192
forge install: openzeppelin-contracts
shazow 3bb2516
Switch solmate to openzeppelin, mainly owned to ownable
shazow c1cda84
reorg layout, add interfacs and extended dirs
shazow 01a63e7
src: Registrar: Pull out internal helpers, permission checking
shazow fb9dc95
WIP: src/extended/PermitRegistrarWithReverse.sol
shazow 704eac4
WIP: src/extended/PermitRegistrarWithReverse.sol
shazow eabf852
src/extended/PermitRegistrarWithReverse.sol: Rename const
shazow 2d9a3dd
src, test: PermitRegistrarWithReverse is working
shazow cbdbe4c
test: PermitRegistrar permutations
shazow ebc4d1c
Add documentation
shazow 75deb4e
test/Helpers.sol: Remove unused ReverseHelpers
shazow 5d448a1
README: Clarify namehash
shazow 6c5ad75
skyteller -> example
shazow File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| name: test | ||
|
|
||
| on: workflow_dispatch | ||
|
|
||
| env: | ||
| FOUNDRY_PROFILE: ci | ||
|
|
||
| jobs: | ||
| check: | ||
| strategy: | ||
| fail-fast: true | ||
|
|
||
| name: Foundry project | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v3 | ||
| with: | ||
| submodules: recursive | ||
|
|
||
| - name: Install Foundry | ||
| uses: foundry-rs/foundry-toolchain@v1 | ||
| with: | ||
| version: nightly | ||
|
|
||
| - name: Run Forge build | ||
| run: | | ||
| forge --version | ||
| forge build --sizes | ||
| id: build | ||
|
|
||
| - name: Run Forge tests | ||
| run: | | ||
| forge test -vvv | ||
| id: test |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| # Compiler files | ||
| cache/ | ||
| out/ | ||
|
|
||
| # Ignores development broadcast logs | ||
| !/broadcast | ||
| /broadcast/*/31337/ | ||
| /broadcast/**/dry-run/ | ||
|
|
||
| # Docs | ||
| docs/ | ||
|
|
||
| # Dotenv file | ||
| .env | ||
|
|
||
| /.* |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| [submodule "lib/forge-std"] | ||
| path = lib/forge-std | ||
| url = https://github.com/foundry-rs/forge-std | ||
| [submodule "lib/ens-contracts"] | ||
| path = lib/ens-contracts | ||
| url = https://github.com/ensdomains/ens-contracts | ||
| [submodule "lib/openzeppelin-contracts"] | ||
| path = lib/openzeppelin-contracts | ||
| url = https://github.com/OpenZeppelin/openzeppelin-contracts |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| build: | ||
| forge build | ||
|
|
||
| test: | ||
| forge test --offline -vv | ||
|
|
||
| gas-report: | ||
| NUM=100 forge test --offline --gas-report --match-test "test_Set|test_Multiset|test_RegisterWithPermit" | ||
|
|
||
| fork: | ||
| anvil --fork-url "$(ETH_RPC_URL)" | ||
|
|
||
| deploy: | ||
| # ENV should include ETH_RPC_URL, ETH_PRIVATE_KEY, ETH_OWNER_ADDRESS | ||
| forge script script/ManagedENSResolver.s.sol:Deploy --rpc-url "$(ETH_RPC_URL)" --broadcast --verify -vvvv | ||
|
|
||
| # Call `make fork` and grab one of the forked private keys | ||
| # export ETH_PRIVATE_KEY="0x..." | ||
| # Note that this will produce a ./broadcast output | ||
| deploy-forked: | ||
| forge script script/ManagedENSResolver.s.sol:Deploy --rpc-url "http://127.0.0.1:8545" --broadcast -vvvv | ||
|
|
||
| .PHONY: test build |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,61 @@ | ||
| # skyteller-ens-registry | ||
| # ENS Managed Registry | ||
|
|
||
| ## Getting Started | ||
|
|
||
| ``` | ||
| $ nix develop # or install foundry some other way | ||
| $ make test # or `forge test` | ||
| ``` | ||
|
|
||
| ## Overview | ||
|
|
||
| ### `src/ManagedRegistrar.sol` | ||
|
|
||
| A simple managed registrar, allowing an admin to set namehash node to address | ||
| mappings. | ||
|
|
||
| Note: ENS operates on recursive domain component hashes ([namehash](https://docs.ens.domains/contract-api-reference/name-processing)) rather than DNS-style domain strings. Roughly speaking, `foo.example.eth`'s namehash is: | ||
|
|
||
| ``` | ||
| sha3( | ||
| sha3( | ||
| sha3( | ||
| bytes32(0x0) + sha3("eth") | ||
| ) + sha3("example") | ||
| ) + sha3("foo") | ||
| ) | ||
| ``` | ||
|
|
||
| When a client is resolving a domain, the namehash is provided. | ||
|
|
||
|
|
||
| ### `src/Resolver.sol` | ||
|
|
||
| A wildcard ENS resolver that uses a registrar (like `ManagedRegistrar` above) as a backend. | ||
|
|
||
| Note: [Wildcard resolvers](https://docs.ens.domains/ens-improvement-proposals/ensip-10-wildcard-resolution) are different from the original ENS subnode-based resolver, which relied on registering every subdomain on ENS's central subnode registry. With wildcard resolvers, the client is expected to recursively attempt to find a resolver for each level until it succeeds: First `foo.example.eth`, if no resolver is registered then check `example.eth`, if no resolver then fall back to the default `eth` resolver. | ||
|
|
||
| ### `src/extended/ManagedENSResolver.sol` | ||
|
|
||
| Builds on top of the basic Resolver, except it adds a wrapper `register(...)` helper which also performs subnode registering for each subdomain. | ||
|
|
||
| This is mainly to demonstrate what it would take to support even naive resolvers, and to measure the gas difference. | ||
|
|
||
| ### `src/extended/ChildResolver.sol` | ||
|
|
||
| Wrapper around another Resolver which proxies all of the optional fields as available default values. If we want to maintain all of the set field values on today's production resolver without reapplying them to a new resolver's state, we can use this. | ||
|
|
||
| ### `src/extended/ManagedRegistrarWithReverse.sol` | ||
|
|
||
| Builds on top of a basic ManagedRegistrar, but adds reverse name lookup registration. Some DApps use this to convert addresses to ENS names for display purposes. | ||
|
|
||
| Setting a name mapping is an additional call, with additional gas costs. | ||
|
|
||
| ### `src/extended/PermitRegistrarWithReverse.sol` | ||
|
|
||
| Builds on top of ManagedRegistrarWithReverse, except the user pays for the gas costs of registering their subdomain. A signature oracle provides a signed digest that a user can use to claim a name. A reverse name mapping is set at the same time. | ||
|
|
||
|
|
||
| ## License | ||
|
|
||
| MIT | ||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| { | ||
| inputs = { | ||
| utils.url = "github:numtide/flake-utils"; | ||
| foundry.url = "github:shazow/foundry.nix/monthly"; # Use monthly branch for permanent releases | ||
| }; | ||
|
|
||
| outputs = { self, nixpkgs, utils, foundry }: | ||
| utils.lib.eachDefaultSystem (system: | ||
| let | ||
| pkgs = import nixpkgs { | ||
| inherit system; | ||
| overlays = [ foundry.overlay ]; | ||
| }; | ||
| in { | ||
|
|
||
| devShell = with pkgs; mkShell { | ||
| buildInputs = [ | ||
| # From the foundry overlay | ||
| # Note: Can also be referenced without overlaying as: foundry.defaultPackage.${system} | ||
| foundry-bin | ||
|
|
||
| # ... any other dependencies we need | ||
| #solc | ||
| ]; | ||
|
|
||
| # Decorative prompt override so we know when we're in a dev shell | ||
| shellHook = '' | ||
| export PS1="[dev] $PS1" | ||
| ''; | ||
| }; | ||
| }); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| [profile.default] | ||
| src = "src" | ||
| out = "out" | ||
| libs = ["lib"] | ||
|
|
||
| # See more config options https://github.com/foundry-rs/foundry/tree/master/config |
Submodule ens-contracts
added at
f5f2ed
Submodule openzeppelin-contracts
added at
0a25c1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| // SPDX-License-Identifier: MIT | ||
| pragma solidity ^0.8.13; | ||
|
|
||
| import "forge-std/Script.sol"; | ||
|
|
||
| import {ManagedENSResolver} from "../src/extended/ManagedENSResolver.sol"; | ||
| import {ManagedRegistrarWithReverse} from "../src/extended/ManagedRegistrarWithReverse.sol"; | ||
|
|
||
| import {Helpers} from "../test/Helpers.sol"; | ||
|
|
||
| contract Deploy is Script { | ||
| function run() public { | ||
| uint256 deployerPrivateKey = vm.envUint("ETH_PRIVATE_KEY"); | ||
| address ownerAddress = vm.envAddress("ETH_OWNER_ADDRESS"); | ||
|
|
||
| vm.startBroadcast(deployerPrivateKey); | ||
|
|
||
| ManagedRegistrarWithReverse registrar = new ManagedRegistrarWithReverse(); | ||
| new ManagedENSResolver( | ||
| registrar, // IRegistrar | ||
| registrar, // INameResolver | ||
| Helpers.namehash("example", "eth") // parentNode | ||
| ); | ||
|
|
||
| bytes32 ownerNode = Helpers.namehash("owner", "example", "eth"); | ||
| registrar.set(ownerNode, ownerAddress); | ||
|
|
||
| if (ownerAddress != address(0)) { | ||
| console.log("Changing registrar owner: %s -> %s", registrar.owner(), ownerAddress); | ||
| registrar.transferOwnership(ownerAddress); | ||
| } | ||
|
|
||
| vm.stopBroadcast(); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| // SPDX-License-Identifier: MIT | ||
| pragma solidity ^0.8.13; | ||
|
|
||
| import "forge-std/Script.sol"; | ||
|
|
||
| interface ENS { | ||
| function resolver(bytes32 node) external view returns (address); | ||
| function owner(bytes32 node) external view returns (address); | ||
|
|
||
| function setResolver(bytes32 node, address resolver) external; | ||
| } | ||
|
|
||
| // FIXME: This isn't working with impersonate. Use the cast-based script instead for now. | ||
|
|
||
| // Override replaces the ENS resolver in a forked environment, for testing. | ||
| // We use --unlocked --sender "0x4863A39d26F8b2e40d2AAbFf1eEe55E4B5015C4f" | ||
| contract Override is Script { | ||
| function run() public { | ||
| address resolverAddress = vm.envAddress("RESOLVER_ADDRESS"); | ||
|
|
||
| ENS ens = ENS(0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e); | ||
|
|
||
| bytes32 exampleNode = 0x3d5d2e21162745e4df4f56471fd7f651f441adaaca25deb70e4738c6f63d1224; | ||
| address currentOwner = ens.owner(exampleNode); | ||
|
|
||
| vm.startBroadcast(currentOwner); | ||
|
|
||
| // Replace the resolver | ||
| ens.setResolver(exampleNode, resolverAddress); | ||
|
|
||
| console.log("New resolver: %s", ens.resolver(exampleNode)); | ||
|
|
||
| vm.stopBroadcast(); | ||
|
|
||
| // $ cast call --rpc-url "http://127.0.0.1:8545" 0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e "resolver(bytes32) returns (address)" "0x3d5d2e21162745e4df4f56471fd7f651f441adaaca25deb70e4738c6f63d1224" | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Forgot one more thing here: The target address for reverse lookup needs to register a resolver with the global ENS contract: https://docs.ens.domains/contract-api-reference/reverseregistrar
If the target address is a contact (e.g. the skyteller proxy), then the contract would need to call that. This would require adding a helper function to the skyteller proxy (or doing it on init).