Skip to content

Commit

Permalink
refactor: contracts compliant with new version of the ENSIP
Browse files Browse the repository at this point in the history
  • Loading branch information
pikonha committed Jan 23, 2025
1 parent b3de6c7 commit 8438b27
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 161 deletions.
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@ This project not only makes ENS more efficient and cost-effective but also opens

| Contract | Network | Address |
| --------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------- |
| DatabaseResolver | Ethereum | [0xc1D4903Eba794035d2D81D210325b57a95C8a007](https://sepolia.etherscan.io/address/0xc1D4903Eba794035d2D81D210325b57a95C8a007) |
| DatabaseResolver | Ethereum | [0x464e965E2BA20430d9E35c815c8F73a76D5ea4F6](https://sepolia.etherscan.io/address/0x464e965E2BA20430d9E35c815c8F73a76D5ea4F6) |
| ArbitrumVerifier | Ethereum | [0x8fc4a214705e3c40032e99f867d964c012bf8efb](https://sepolia.etherscan.io/address/0x8fc4a214705e3c40032e99f867d964c012bf8efb) |
| L1Resolver | Ethereum | [0xF0c1d78C73B2fCBF17e1c4DbBBD9df30a9556BB8](https://sepolia.etherscan.io/address/0xF0c1d78C73B2fCBF17e1c4DbBBD9df30a9556BB8) |
| L1Resolver | Ethereum | [0xa0038AD12102c9Fbe7163D5b1bb286E6F678b4df](https://sepolia.etherscan.io/address/0xa0038AD12102c9Fbe7163D5b1bb286E6F678b4df) |
| ENSRegistry | Arbitrum | [0x8d55e297c37993ebbd2e7a8d7688f7e5b35f1b50](https://sepolia.arbiscan.io/address/0x8d55e297c37993ebbd2e7a8d7688f7e5b35f1b50) |
| ReverseRegistrar | Arbitrum | [0xb3c9ff08671bbadddd0436cc46fbfa005c8da0a7](https://sepolia.arbiscan.io/address/0xb3c9ff08671bbadddd0436cc46fbfa005c8da0a7) |
| BaseRegistrarImplementation | Arbitrum | [0x2C6a113C513fa0fd404abcCE3aC8a4BE16ccb651](https://sepolia.arbiscan.io/address/0x2C6a113C513fa0fd404abcCE3aC8a4BE16ccb651) |
| NameWrapper | Arbitrum | [0xff4f34ac12a84de527cf9e24856fc8d7c42cc379](https://sepolia.arbiscan.io/address/0xff4f34ac12a84de527cf9e24856fc8d7c42cc379) |
| ETHRegistrarController | Arbitrum | [0x263c644d8f5d4bdb44cfab020491ec6fc4ca5271](https://sepolia.arbiscan.io/address/0x263c644d8f5d4bdb44cfab020491ec6fc4ca5271) |
| SubdomainController | Arbitrum | [0x41eede073217084a30f6f3bc2c546bda1f08b5ca](https://sepolia.arbiscan.io/address/0x41eede073217084a30f6f3bc2c546bda1f08b5ca) |
| SubdomainController | Arbitrum | [0x2e28f723818ED7B70a3ec10879309aa39CC4b3D6](https://sepolia.arbiscan.io/address/0x2e28f723818ED7B70a3ec10879309aa39CC4b3D6) |
| PublicResolver | Arbitrum | [0x0a33f065c9c8f0F5c56BB84b1593631725F0f3af](https://sepolia.arbiscan.io/address/0x0a33f065c9c8f0F5c56BB84b1593631725F0f3af) |

## Components
Expand Down Expand Up @@ -79,7 +79,7 @@ try {
})
} catch (err) {
const data = getRevertErrorData(err)
if (data?.errorName === 'StorageHandledByOffChainDatabase') {
if (data?.errorName === 'OperationHandledOffchain') {
const [domain, url, message] = data.args as [
DomainData,
string,
Expand All @@ -104,7 +104,7 @@ try {
})
} catch (err) {
const data = getRevertErrorData(err)
if (data?.errorName === 'StorageHandledByL2') {
if (data?.errorName === 'OperationHandledOnchain') {
const [chainId, contractAddress] = data.args as [bigint, `0x${string}`]

await handleL2Storage({
Expand Down Expand Up @@ -290,7 +290,7 @@ Domain Register:
1. Find the resolver associated with the given domain through the Universal Resolver
2. Call the `register` function on the resolver passing the address of the Layer 2 resolver that will be managing the properties of a given domain
3. Client calls `setOwner` on the L1 Resolver
4. Client receive a `StorageHandledByL2` revert with the arguments required to call the gateway
4. Client receive a `OperationHandledOnchain` revert with the arguments required to call the gateway
5. Client calls the L2 Resolver with the returned arguments

![domain register](https://github.com/blockful-io/external-resolver/assets/29408363/1ef65db2-a979-4e2f-bb9f-7dde0769fae4)
Expand Down
4 changes: 2 additions & 2 deletions packages/client/test/db.e2e.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ async function offchainWriting({
args: [
encodedName,
encodeFunctionData({
functionName: 'getDeferralHandler',
functionName: 'getOperationHandler',
abi: abiDBResolver,
args: [encodeFunctionData(calldata)],
}),
Expand All @@ -105,7 +105,7 @@ async function offchainWriting({
abi: abiDBResolver,
data: params as Hex,
})
if (errorResult?.errorName === 'StorageHandledByOffChainDatabase') {
if (errorResult?.errorName === 'OperationHandledOffchain') {
const [domain, url, message] = errorResult?.args as [
DomainData,
string,
Expand Down
22 changes: 11 additions & 11 deletions packages/contracts/src/DatabaseResolver.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {IMulticallable} from "@ens-contracts/resolvers/IMulticallable.sol";

import {ENSIP16} from "./ENSIP16.sol";
import {SignatureVerifier} from "./SignatureVerifier.sol";
import {IWriteDeferral} from "./interfaces/IWriteDeferral.sol";
import {OperationRouter} from "./interfaces/OperationRouter.sol";
import {EnumerableSetUpgradeable} from "./utils/EnumerableSetUpgradeable.sol";

/**
Expand All @@ -31,7 +31,7 @@ contract DatabaseResolver is
ERC165,
ENSIP16,
IExtendedResolver,
IWriteDeferral,
OperationRouter,
AddrResolver,
ABIResolver,
PubkeyResolver,
Expand Down Expand Up @@ -112,9 +112,9 @@ contract DatabaseResolver is
* @notice Read call for fetching the required parameters for the offchain call
* @notice avoiding multiple transactions
* @param data The encoded data to be written
* @dev This function reverts with StorageHandledByL2 error to indicate L2 deferral
* @dev This function reverts with OperationHandledOnchain error to indicate L2 deferral
*/
function getDeferralHandler(bytes calldata data) public view override {
function getOperationHandler(bytes calldata data) public view override {
_offChainStorage(data);
}

Expand Down Expand Up @@ -143,9 +143,9 @@ contract DatabaseResolver is
return bytes(this.name(node));
}

if (bytes4(data[:4]) == this.getDeferralHandler.selector) {
if (bytes4(data[:4]) == this.getOperationHandler.selector) {
(bytes memory _data) = abi.decode(data[4:], (bytes));
this.getDeferralHandler(_data);
this.getOperationHandler(_data);
}

_offChainLookup(data);
Expand Down Expand Up @@ -418,18 +418,18 @@ contract DatabaseResolver is
//////// ENS WRITE DEFERRAL RESOLVER (EIP-5559) ////////

/**
* @notice Builds an StorageHandledByOffChainDatabase error.
* @notice Builds an OperationHandledOffchain error.
*/
function _offChainStorage(bytes calldata callData) private view {
revert StorageHandledByOffChainDatabase(
IWriteDeferral.domainData({
revert OperationHandledOffchain(
OperationRouter.DomainData({
name: _WRITE_DEFERRAL_DOMAIN_NAME,
version: _WRITE_DEFERRAL_DOMAIN_VERSION,
chainId: _CHAIN_ID,
verifyingContract: address(this)
}),
gatewayUrl,
IWriteDeferral.messageData({
OperationRouter.MessageData({
data: callData,
sender: msg.sender,
expirationTimestamp: block.timestamp
Expand Down Expand Up @@ -568,7 +568,7 @@ contract DatabaseResolver is
)
returns (bool)
{
return interfaceID == type(IWriteDeferral).interfaceId
return interfaceID == type(OperationRouter).interfaceId
|| interfaceID == type(IExtendedResolver).interfaceId
|| interfaceID == type(IMulticallable).interfaceId
|| super.supportsInterface(interfaceID);
Expand Down
26 changes: 9 additions & 17 deletions packages/contracts/src/L1Resolver.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,27 +22,21 @@ import {ENSIP16} from "./ENSIP16.sol";
import {EVMFetcher} from "./evmgateway/EVMFetcher.sol";
import {IEVMVerifier} from "./evmgateway/IEVMVerifier.sol";
import {EVMFetchTarget} from "./evmgateway/EVMFetchTarget.sol";
import {IWriteDeferral} from "./interfaces/IWriteDeferral.sol";
import {OperationRouter} from "./interfaces/OperationRouter.sol";
import {OffchainRegister} from "./interfaces/WildcardWriting.sol";

contract L1Resolver is
EVMFetchTarget,
IExtendedResolver,
IERC165,
IWriteDeferral,
OperationRouter,
IMulticallable,
Ownable,
ENSIP16
{

using EVMFetcher for EVMFetcher.EVMFetchRequest;

//////// ERRORS ////////

/// @notice Error thrown when an unsupported function is called
/// @dev Used to indicate when a function call is not implemented or allowed
error FunctionNotSupported();

//////// CONTRACT VARIABLE STATE ////////

// address of each target contract
Expand Down Expand Up @@ -109,9 +103,9 @@ contract L1Resolver is
/**
* @notice Validates and processes write parameters for deferred storage mutations
* @param data The encoded data to be written
* @dev This function reverts with StorageHandledByL2 error to indicate L2 deferral
* @dev This function reverts with OperationHandledOnchain error to indicate L2 deferral
*/
function getDeferralHandler(bytes calldata data) public view override {
function getOperationHandler(bytes calldata data) public view override {
bytes4 selector = bytes4(data);

if (selector == OffchainRegister.register.selector) {
Expand Down Expand Up @@ -169,9 +163,9 @@ contract L1Resolver is
bytes32 node = abi.decode(data[4:], (bytes32));
return _contenthash(node);
}
if (selector == this.getDeferralHandler.selector) {
if (selector == this.getOperationHandler.selector) {
(bytes memory _data) = abi.decode(data[4:], (bytes));
this.getDeferralHandler(_data);
this.getOperationHandler(_data);
}
}

Expand Down Expand Up @@ -366,10 +360,10 @@ contract L1Resolver is
//////// ENS WRITE DEFERRAL RESOLVER (EIP-5559) ////////

/**
* @notice Builds an StorageHandledByL2 error.
* @notice Builds an OperationHandledOnchain error.
*/
function _offChainStorage(address target) internal view {
revert StorageHandledByL2(chainId, target);
revert OperationHandledOnchain(chainId, target);
}

//////// ENS ERC-165 ////////
Expand All @@ -381,7 +375,7 @@ contract L1Resolver is
returns (bool)
{
return interfaceID == type(IExtendedResolver).interfaceId
|| interfaceID == type(IWriteDeferral).interfaceId
|| interfaceID == type(OperationRouter).interfaceId
|| interfaceID == type(EVMFetchTarget).interfaceId
|| interfaceID == type(IERC165).interfaceId
|| interfaceID == type(ENSIP16).interfaceId
Expand All @@ -407,9 +401,7 @@ contract L1Resolver is
* @param target The L2 contract address
*/
function setTarget(bytes32 key, address target) public onlyOwner {
address prevAddr = targets[key];
targets[key] = target;
emit L2HandlerContractAddressChanged(chainId, prevAddr, target);
}

function multicall(bytes[] calldata /* data */ )
Expand Down
101 changes: 0 additions & 101 deletions packages/contracts/src/interfaces/IWriteDeferral.sol

This file was deleted.

64 changes: 64 additions & 0 deletions packages/contracts/src/interfaces/OperationRouter.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

interface OperationRouter {

/**
* @dev Error to raise when an encoded function that is not supported
* @dev is received on the getOperationHandler function
*/
error FunctionNotSupported();

/**
* @dev Error to raise when mutations are being deferred onchain
* that being the layer 1 or a layer 2
* @param chainId Chain ID to perform the deferred mutation to.
* @param contractAddress Contract Address at which the deferred mutation should transact with.
*/
error OperationHandledOnchain(uint256 chainId, address contractAddress);

/**
* @notice Struct used to define the domain of the typed data signature, defined in EIP-712.
* @param name The user friendly name of the contract that the signature corresponds to.
* @param version The version of domain object being used.
* @param chainId The ID of the chain that the signature corresponds to
* @param verifyingContract The address of the contract that the signature pertains to.
*/
struct DomainData {
string name;
string version;
uint64 chainId;
address verifyingContract;
}

/**
* @notice Struct used to define the message context for off-chain storage authorization
* @param data The original ABI encoded function call
* @param sender The address of the user performing the mutation (msg.sender).
* @param expirationTimestamp The timestamp at which the mutation will expire.
*/
struct MessageData {
bytes data;
address sender;
uint256 expirationTimestamp;
}

/**
* @dev Error to raise when mutations are being deferred to an Offchain entity
* @param sender the EIP-712 domain definition
* @param url URL to request to perform the off-chain mutation
* @param data The original ABI encoded function call along with authorization context
*/
error OperationHandledOffchain(
DomainData sender, string url, MessageData data
);

/**
* @notice Determines the appropriate handler for an encoded function call
* @param encodedFunction The ABI encoded function call
*/
function getOperationHandler(bytes calldata encodedFunction)
external
view;

}
Loading

0 comments on commit 8438b27

Please sign in to comment.