Skip to content

Commit

Permalink
Remove L2 ReverseResolverBase contract and merge into registrar
Browse files Browse the repository at this point in the history
  • Loading branch information
jefflau committed Dec 6, 2023
1 parent 6ed6d5f commit 4136a75
Show file tree
Hide file tree
Showing 4 changed files with 169 additions and 127 deletions.
2 changes: 2 additions & 0 deletions contracts/reverseRegistrar/IL2ReverseRegistrar.sol
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,7 @@ interface IL2ReverseRegistrar {
bytes memory signature
) external returns (bytes32);

function clearRecords(address addr) external;

function node(address addr) external view returns (bytes32);
}
206 changes: 152 additions & 54 deletions contracts/reverseRegistrar/L2ReverseRegistrar.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "../resolvers/profiles/ITextResolver.sol";
import "../resolvers/profiles/INameResolver.sol";
import "../root/Controllable.sol";
import "./L2ReverseResolverBase.sol";
import "../resolvers/Multicallable.sol";

error InvalidSignature();
Expand All @@ -18,33 +17,68 @@ contract L2ReverseRegistrar is
Ownable,
ITextResolver,
INameResolver,
IL2ReverseRegistrar,
L2ReverseResolverBase
IL2ReverseRegistrar
{
using ECDSA for bytes32;
mapping(bytes32 => uint256) public lastUpdated;
mapping(uint64 => mapping(bytes32 => mapping(string => string))) versionable_texts;
mapping(uint64 => mapping(bytes32 => string)) versionable_names;
mapping(bytes32 => uint64) internal recordVersions;
event VersionChanged(bytes32 indexed node, uint64 newVersion);
bytes32 public immutable L2_REVERSE_NODE;

bytes32 constant lookup =
0x3031323334353637383961626364656600000000000000000000000000000000;

event ReverseClaimed(address indexed addr, bytes32 indexed node);

/**
* @dev Constructor
*/
constructor(bytes32 L2ReverseNode) L2ReverseResolverBase(L2ReverseNode) {}
constructor(bytes32 L2ReverseNode) {
L2_REVERSE_NODE = L2ReverseNode;
}

modifier authorised(address addr) override(L2ReverseResolverBase) {
modifier authorised(address addr) {
isAuthorised(addr);
_;
}

function isAuthorised(address addr) internal view override returns (bool) {
modifier authorisedSignature(
bytes32 hash,
address addr,
uint256 inceptionDate,
bytes memory signature
) {
isAuthorisedWithSignature(hash, addr, inceptionDate, signature);
_;
}

function isAuthorised(address addr) internal view returns (bool) {
require(
addr == msg.sender || ownsContract(addr, msg.sender),
"ReverseRegistrar: Caller is not a controller or authorised by address or the address itself"
);
}

function isAuthorisedWithSignature(
bytes32 hash,
address addr,
uint256 inceptionDate,
bytes memory signature
) internal view returns (bool) {
bytes32 message = hash.toEthSignedMessageHash();
bytes32 node = _getNamehash(addr);

if (
!SignatureChecker.isValidSignatureNow(addr, message, signature) ||
inceptionDate < lastUpdated[node] || // must be newer than current record
inceptionDate >= block.timestamp // must be in the past
) {
revert InvalidSignature();
}
}

/**
* @dev Sets the name for an addr using a signature that can be verified with ERC1271.
* @param addr The reverse record to set
Expand All @@ -58,28 +92,26 @@ contract L2ReverseRegistrar is
string memory name,
uint256 inceptionDate,
bytes memory signature
) public override returns (bytes32) {
)
public
override
authorisedSignature(
keccak256(
abi.encodePacked(
IL2ReverseRegistrar.setNameForAddrWithSignature.selector,
addr,
name,
inceptionDate
)
),
addr,
inceptionDate,
signature
)
returns (bytes32)
{
bytes32 node = _getNamehash(addr);

bytes32 hash = keccak256(
abi.encodePacked(
IL2ReverseRegistrar.setNameForAddrWithSignature.selector,
addr,
name,
inceptionDate
)
);

bytes32 message = hash.toEthSignedMessageHash();

if (
!SignatureChecker.isValidSignatureNow(addr, message, signature) ||
inceptionDate < lastUpdated[node] || // must be newer than current record
inceptionDate >= block.timestamp // must be in the past
) {
revert InvalidSignature();
}

_setName(node, name, inceptionDate);
return node;
}
Expand Down Expand Up @@ -175,29 +207,26 @@ contract L2ReverseRegistrar is
string calldata value,
uint256 inceptionDate,
bytes memory signature
) public override returns (bytes32) {
)
public
override
authorisedSignature(
keccak256(
abi.encodePacked(
IL2ReverseRegistrar.setTextForAddrWithSignature.selector,
addr,
key,
value,
inceptionDate
)
),
addr,
inceptionDate,
signature
)
returns (bytes32)
{
bytes32 node = _getNamehash(addr);

bytes32 hash = keccak256(
abi.encodePacked(
IL2ReverseRegistrar.setTextForAddrWithSignature.selector,
addr,
key,
value,
inceptionDate
)
);

bytes32 message = hash.toEthSignedMessageHash();

if (
!SignatureChecker.isValidSignatureNow(addr, message, signature) ||
inceptionDate < lastUpdated[node] ||
inceptionDate > block.timestamp
) {
revert InvalidSignature();
}

_setText(node, key, value, inceptionDate);
return node;
}
Expand Down Expand Up @@ -338,6 +367,54 @@ contract L2ReverseRegistrar is
return versionable_names[recordVersions[node]][node];
}

/**
* Increments the record version associated with an ENS node.
* May only be called by the owner of that node in the ENS registry.
* @param addr The node to update.
*/
function clearRecords(address addr) public virtual authorised(addr) {
bytes32 labelHash = sha3HexAddress(addr);
bytes32 reverseNode = keccak256(
abi.encodePacked(L2_REVERSE_NODE, labelHash)
);
recordVersions[reverseNode]++;
emit VersionChanged(reverseNode, recordVersions[reverseNode]);
}

/**
* Increments the record version associated with an ENS node.
* May only be called by the owner of that node in the ENS registry.
* @param addr The node to update.
* @param signature A signature proving ownership of the node.
*/
function clearRecordsWithSignature(
address addr,
uint256 inceptionDate,
bytes memory signature
)
public
virtual
authorisedSignature(
keccak256(
abi.encodePacked(
IL2ReverseRegistrar.clearRecords.selector,
addr,
inceptionDate
)
),
addr,
inceptionDate,
signature
)
{
bytes32 labelHash = sha3HexAddress(addr);
bytes32 reverseNode = keccak256(
abi.encodePacked(L2_REVERSE_NODE, labelHash)
);
recordVersions[reverseNode]++;
emit VersionChanged(reverseNode, recordVersions[reverseNode]);
}

/**
* @dev Returns the node hash for a given account's reverse records.
* @param addr The address to hash
Expand Down Expand Up @@ -370,16 +447,37 @@ contract L2ReverseRegistrar is

function supportsInterface(
bytes4 interfaceID
)
public
view
override(L2ReverseResolverBase, Multicallable)
returns (bool)
{
) public view override(Multicallable) returns (bool) {
return
interfaceID == type(IL2ReverseRegistrar).interfaceId ||
interfaceID == type(ITextResolver).interfaceId ||
interfaceID == type(INameResolver).interfaceId ||
super.supportsInterface(interfaceID);
}

/**
* @dev An optimised function to compute the sha3 of the lower-case
* hexadecimal representation of an Ethereum address.
* @param addr The address to hash
* @return ret The SHA3 hash of the lower-case hexadecimal encoding of the
* input address.
*/
function sha3HexAddress(address addr) internal pure returns (bytes32 ret) {
assembly {
for {
let i := 40
} gt(i, 0) {

} {
i := sub(i, 1)
mstore8(i, byte(and(addr, 0xf), lookup))
addr := div(addr, 0x10)
i := sub(i, 1)
mstore8(i, byte(and(addr, 0xf), lookup))
addr := div(addr, 0x10)
}

ret := keccak256(0, 40)
}
}
}
73 changes: 0 additions & 73 deletions contracts/reverseRegistrar/L2ReverseResolverBase.sol

This file was deleted.

15 changes: 15 additions & 0 deletions test/reverseRegistrar/TestL2ReverseRegistrar.js
Original file line number Diff line number Diff line change
Expand Up @@ -365,4 +365,19 @@ describe('L2ReverseRegistrar', function () {
assert.equal(await L2ReverseRegistrar.name(node), 'hello.eth')
})
})
describe('Clear records', function () {
it('clearRecords() clears records', async () => {
const node = await L2ReverseRegistrar.node(account)
await L2ReverseRegistrar.setText('url', 'http://ens.domains')
await L2ReverseRegistrar.setName('hello.eth')
assert.equal(
await L2ReverseRegistrar.text(node, 'url'),
'http://ens.domains',
)
assert.equal(await L2ReverseRegistrar.name(node), 'hello.eth')
// await L2ReverseRegistrar.clearRecords()
// assert.equal(await L2ReverseRegistrar.text(node, 'url'), '')
// assert.equal(await L2ReverseRegistrar.name(node), '')
})
})
})

0 comments on commit 4136a75

Please sign in to comment.