Compare commits
3 Commits
7be69e8f7f
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 0cff07f2e7 | |||
| a468828000 | |||
| ed66629365 |
@@ -33,6 +33,10 @@ or
|
|||||||
npm run test:linux
|
npm run test:linux
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Contracts
|
||||||
|
|
||||||
|
Proposal deployed contract: [etherscan link](https://etherscan.io/address/0x86d5f637f7cc0e55334439d0495de3b7daa62baa#code)
|
||||||
|
|
||||||
### Verification
|
### Verification
|
||||||
|
|
||||||
Since the proposal code can be confusing because it relies on numerous specifications and EIPs, users can use scripts to verify the correctness of the data, see the output in the corresponding files, and insert the code directly into Solidity, comparing it with the existing code in the proposal (there should be no discrepancies be).
|
Since the proposal code can be confusing because it relies on numerous specifications and EIPs, users can use scripts to verify the correctness of the data, see the output in the corresponding files, and insert the code directly into Solidity, comparing it with the existing code in the proposal (there should be no discrepancies be).
|
||||||
|
|||||||
@@ -5,5 +5,13 @@ pragma solidity ^0.8.19;
|
|||||||
interface IENSRegistry {
|
interface IENSRegistry {
|
||||||
function setSubnodeOwner(bytes32 node, bytes32 label, address owner) external returns (bytes32);
|
function setSubnodeOwner(bytes32 node, bytes32 label, address owner) external returns (bytes32);
|
||||||
|
|
||||||
|
function setSubnodeRecord(bytes32 node, bytes32 label, address owner, address resolver, uint64 ttl) external;
|
||||||
|
|
||||||
|
function resolver(bytes32 node) external view returns (address);
|
||||||
|
|
||||||
function setOwner(bytes32 node, address owner) external;
|
function setOwner(bytes32 node, address owner) external;
|
||||||
|
|
||||||
|
function owner(bytes32 node) external view returns (address);
|
||||||
|
|
||||||
|
function recordExists(bytes32 node) external view returns (bool);
|
||||||
}
|
}
|
||||||
|
|||||||
39
test/ENSNamehash.sol
Normal file
39
test/ENSNamehash.sol
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
pragma solidity ^0.8.19;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @dev Solidity implementation of the ENS namehash algorithm.
|
||||||
|
*
|
||||||
|
* Warning! Does not normalize or validate names before hashing.
|
||||||
|
*/
|
||||||
|
library ENSNamehash {
|
||||||
|
function namehash(bytes memory domain) internal pure returns (bytes32) {
|
||||||
|
return namehash(domain, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function namehash(bytes memory domain, uint256 i) internal pure returns (bytes32) {
|
||||||
|
if (domain.length <= i) {
|
||||||
|
return 0x0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint256 len = LabelLength(domain, i);
|
||||||
|
|
||||||
|
return keccak256(abi.encodePacked(namehash(domain, i + len + 1), keccak(domain, i, len)));
|
||||||
|
}
|
||||||
|
|
||||||
|
function LabelLength(bytes memory domain, uint256 i) private pure returns (uint256) {
|
||||||
|
uint256 len;
|
||||||
|
while (i + len != domain.length && domain[i + len] != 0x2e) {
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
function keccak(bytes memory data, uint256 offset, uint256 len) private pure returns (bytes32 ret) {
|
||||||
|
require(offset + len <= data.length);
|
||||||
|
assembly {
|
||||||
|
ret := keccak256(add(add(data, 32), offset), len)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,24 +4,97 @@ pragma solidity ^0.8.19;
|
|||||||
|
|
||||||
import { IENSResolver } from "@interfaces/IENSResolver.sol";
|
import { IENSResolver } from "@interfaces/IENSResolver.sol";
|
||||||
import { IENSRegistry } from "@interfaces/IENSRegistry.sol";
|
import { IENSRegistry } from "@interfaces/IENSRegistry.sol";
|
||||||
|
import { ENSNamehash } from "./ENSNamehash.sol";
|
||||||
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
|
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
|
||||||
|
import { TornadoAddresses } from "@proprietary/TornadoAddresses.sol";
|
||||||
|
|
||||||
contract GoerliTestProposal is Ownable {
|
contract GoerliTestProposal is Ownable, TornadoAddresses {
|
||||||
address ensResolverAddress = 0xd7a4F6473f32aC2Af804B3686AE8F1932bC35750; // goerli ENS resolver for testedy.eth
|
address ensResolverAddress = 0xd7a4F6473f32aC2Af804B3686AE8F1932bC35750; // goerli ENS resolver
|
||||||
address ensRegistryAddress = 0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e;
|
address ensRegistryAddress = 0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e;
|
||||||
bytes32 testNode = 0x121818cfd40893900bebefa5ccf60544db43ba8fa1d2d56433984132883bee88; // test.testedy.eth
|
string testDomain = "tornadotest.eth";
|
||||||
|
bytes32 testNode = calculateDomainNode(testDomain);
|
||||||
|
|
||||||
function executeProposal() public onlyOwner {
|
IENSResolver ensResolver = IENSResolver(ensResolverAddress);
|
||||||
IENSResolver ensResolver = IENSResolver(ensResolverAddress);
|
IENSRegistry ensRegistry = IENSRegistry(ensRegistryAddress);
|
||||||
|
|
||||||
|
function transferDomainOwnership(address to) public onlyOwner {
|
||||||
|
_transferDomainOwnership(testNode, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
function transferSubdomainOwnership(string memory domain, string memory subdomainLabel, address to) public onlyOwner {
|
||||||
|
_transferSubdomainOwnership(domain, subdomainLabel, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
function registerSubname(string memory domain, string memory subdomainLabel) public onlyOwner {
|
||||||
|
bytes32 rootNode = calculateDomainNode(domain);
|
||||||
|
address rootResolver = ensRegistry.resolver(rootNode);
|
||||||
|
bytes32 subdomainLabelhash = calculateSubdomainLabelhash(subdomainLabel);
|
||||||
|
|
||||||
|
ensRegistry.setSubnodeRecord(rootNode, subdomainLabelhash, address(this), rootResolver, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _transferDomainOwnership(bytes32 domainNode, address to) private {
|
||||||
|
require(ensRegistry.owner(domainNode) == address(this), "This test contract must be an owner of domain");
|
||||||
|
ensRegistry.setOwner(domainNode, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _transferSubdomainOwnership(string memory domain, string memory subdomainLabel, address to) private {
|
||||||
|
bytes32 rootNode = calculateDomainNode(domain);
|
||||||
|
bytes32 subdomainLabelhash = calculateSubdomainLabelhash(subdomainLabel);
|
||||||
|
bytes32 subdomainNode = keccak256(abi.encodePacked(rootNode, subdomainLabelhash));
|
||||||
|
require(ensRegistry.recordExists(subdomainNode), "Subdomain not registered");
|
||||||
|
require(ensRegistry.owner(rootNode) == address(this), "This test contract must be an owner of domain");
|
||||||
|
|
||||||
|
ensRegistry.setSubnodeOwner(rootNode, subdomainLabelhash, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setNewDomain(string memory newDomain) public onlyOwner {
|
||||||
|
bytes32 newNode = ENSNamehash.namehash(bytes(newDomain));
|
||||||
|
require(ensRegistry.recordExists(newNode), "Node doesn't exist");
|
||||||
|
require(ensRegistry.owner(newNode) == address(this), "Contract is not an owner of new ENS name");
|
||||||
|
transferDomainOwnership(owner());
|
||||||
|
|
||||||
|
testDomain = newDomain;
|
||||||
|
testNode = newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
function calculateDomainNode(string memory domain) internal pure returns (bytes32) {
|
||||||
|
return ENSNamehash.namehash(bytes(domain));
|
||||||
|
}
|
||||||
|
|
||||||
|
function calculateSubdomainLabelhash(string memory subdomainLabel) internal pure returns (bytes32) {
|
||||||
|
return keccak256(bytes(subdomainLabel));
|
||||||
|
}
|
||||||
|
|
||||||
|
function ownSubdomain(string memory domain, string memory subdomainLabel) public {
|
||||||
|
_transferSubdomainOwnership(domain, subdomainLabel, address(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
function setClassicUiIpfs() public {
|
||||||
bytes memory classicUiIPFSContenthash = hex"e301017012208124caa06a8419371b1d2eab9180191727d1ce0c0832975362f77a679ce614b6";
|
bytes memory classicUiIPFSContenthash = hex"e301017012208124caa06a8419371b1d2eab9180191727d1ce0c0832975362f77a679ce614b6";
|
||||||
|
|
||||||
ensResolver.setContenthash(testNode, classicUiIPFSContenthash);
|
ensResolver.setContenthash(testNode, classicUiIPFSContenthash);
|
||||||
}
|
}
|
||||||
|
|
||||||
function returnDomainOwnership() public onlyOwner {
|
function setNovaIpfs() public {
|
||||||
IENSRegistry ensRegistry = IENSRegistry(ensRegistryAddress);
|
bytes memory novaUiIPFSContenthash = hex"e3010170122069648b09fb7ed9a89ca153a000bc8c1bf82a779195a640609e1510dc36c28bb7";
|
||||||
|
|
||||||
ensRegistry.setOwner(testNode, owner());
|
ensResolver.setContenthash(testNode, novaUiIPFSContenthash);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setRelayersNetworkIpfs() public {
|
||||||
|
bytes memory relayersUiIPFSContenthash = hex"e301017012203d61bed0641d7c53d5f036b6448f9d455ae6e0ceda44563009536a12e51d52cf";
|
||||||
|
|
||||||
|
ensResolver.setContenthash(testNode, relayersUiIPFSContenthash);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setDocsIpfs() public {
|
||||||
|
bytes memory docsIPFSContenthash = hex"e3010170122008ba5879914413355290e3c8574825f7a09e59a9802a5fad1edfb3ce6a4f825b";
|
||||||
|
|
||||||
|
ensResolver.setContenthash(testNode, docsIPFSContenthash);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setStakingAddress(string memory domain) public {
|
||||||
|
ensResolver.setAddr(calculateDomainNode(domain), stakingAddress);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user