Created
January 21, 2024 23:11
-
-
Save adraffy/4dbef1e1ef27e4c58c31b1bcca8000d4 to your computer and use it in GitHub Desktop.
This file contains 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
pragma solidity ^0.8.23; | |
import {IERC165} from "@openzeppelin/contracts@4.8.2/utils/introspection/IERC165.sol"; | |
import {ENS} from "https://github.com/ensdomains/ens-contracts/blob/master/contracts/registry/ENS.sol"; | |
import {IExtendedResolver} from "https://github.com/ensdomains/ens-contracts/blob/master/contracts/resolvers/profiles/IExtendedResolver.sol"; | |
import {IMulticallable} from "https://github.com/ensdomains/ens-contracts/blob/master/contracts/resolvers/IMulticallable.sol"; | |
import {BytesUtils} from "https://github.com/ensdomains/ens-contracts/blob/master/contracts/wrapper/BytesUtils.sol"; | |
contract MultiResolver is IERC165, IExtendedResolver { | |
using BytesUtils for bytes; | |
address constant ENS_REGISTRY = 0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e; | |
function supportsInterface(bytes4 x) external pure returns (bool) { | |
return x == type(IERC165).interfaceId // 0x01ffc9a7 | |
|| x == type(IExtendedResolver).interfaceId; // 0x9061b923 | |
} | |
function findResolver(bytes memory name) public view returns (address resolver, bool wildcard, uint256 offset) { | |
while (true) { | |
bytes32 node = name.namehash(offset); | |
resolver = ENS(ENS_REGISTRY).resolver(node); | |
if (resolver != address(0)) break; | |
offset += 1 + uint256(uint8(name[offset])); | |
} | |
try IERC165(resolver).supportsInterface(type(IExtendedResolver).interfaceId) returns (bool support) { | |
require(support || offset == 0); | |
wildcard = support; | |
} catch { | |
revert(); | |
} | |
} | |
error OffchainLookup(address sender, string[] urls, bytes callData, bytes4 callbackFunction, bytes extraData); | |
function resolveCallback(bytes calldata response, bytes calldata wrappedExtraData) external view returns (bytes memory) { | |
(address resolver, bytes4 callbackFunction, bytes memory extraData) = abi.decode(wrappedExtraData, (address, bytes4, bytes)); | |
(bool success, bytes memory data) = resolver.staticcall(abi.encodeWithSelector(callbackFunction, response, extraData)); | |
if (!success) assembly { revert(add(data, 32), mload(data)) } | |
return abi.decode(data, (bytes)); | |
} | |
function resolve(bytes memory name, bytes memory data) external view returns (bytes memory) { | |
(address resolver, bool wildcard, ) = findResolver(name); | |
if (wildcard) { | |
(bool success, bytes memory v) = resolver.staticcall(abi.encodeWithSelector(IExtendedResolver.resolve.selector, name, data)); | |
if (success) return v; // on-chain wildcard | |
assembly { | |
mstore(add(v, 4), sub(mload(v), 4)) | |
v := add(v, 4) | |
} | |
( | |
address sender, | |
string[] memory urls, | |
bytes memory callData, | |
bytes4 callbackFunction, | |
bytes memory extraData | |
) = abi.decode(v, (address, string[], bytes, bytes4, bytes)); | |
require(sender == resolver); | |
revert OffchainLookup( | |
address(this), | |
urls, | |
callData, | |
this.resolveCallback.selector, | |
abi.encode(address(resolver), callbackFunction, extraData) | |
); | |
} | |
if (bytes4(data) == IMulticallable.multicall.selector) { // multicall | |
assembly { | |
mstore(add(data, 4), sub(mload(data), 4)) | |
data := add(data, 4) | |
} | |
bytes[] memory calls = abi.decode(data, (bytes[])); // unbundle the requests | |
for (uint256 i; i < calls.length; i++) { | |
(bool success, bytes memory ret) = resolver.staticcall(calls[i]); // call them directly | |
calls[i] = success ? ret : bytes(''); | |
} | |
return abi.encode(calls); // bundle the results | |
} else { | |
(bool success, bytes memory ret) = resolver.staticcall(data); // single request, call it directly | |
if (!success) assembly { revert(add(ret, 32), mload(ret)) } | |
return ret; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment