Address Contract Verified
Address
0xA155c859Fe3aA782FbADc911947cEfcAC6C35D05
Balance
0 ETH
Nonce
1
Code Size
4608 bytes
Creator
0x8EB07F52...a27F at tx 0x11acf74f...3627a3
Indexed Transactions
0
Contract Bytecode
4608 bytes
0x608060405234801561001057600080fd5b50600436106100b45760003560e01c80638da5cb5b116100715780638da5cb5b146101785780639061b923146101a3578063b4a85801146101b6578063da06e07f146101c9578063eb12d61e146101de578063f2fde38b146101f157600080fd5b806301ffc9a7146100b95780630e316ab7146100e15780636cc895a9146100f6578063736c0d5b14610109578063796676be1461012c5780637df73e271461014c575b600080fd5b6100cc6100c7366004610af0565b610204565b60405190151581526020015b60405180910390f35b6100f46100ef366004610b21565b61023b565b005b6100f4610104366004610be9565b61030e565b6100cc610117366004610b21565b60016020526000908152604090205460ff1681565b61013f61013a366004610cc1565b6103cf565b6040516100d89190610d20565b6100cc61015a366004610b21565b6001600160a01b031660009081526001602052604090205460ff1690565b60025461018b906001600160a01b031681565b6040516001600160a01b0390911681526020016100d8565b61013f6101b1366004610d7c565b61047b565b61013f6101c4366004610d7c565b6104d1565b6101d161065c565b6040516100d89190610de8565b6100f46101ec366004610b21565b610735565b6100f46101ff366004610b21565b610852565b6000639061b92360e01b6001600160e01b03198316148061023557506301ffc9a760e01b6001600160e01b03198316145b92915050565b6002546001600160a01b0316331461026e5760405162461bcd60e51b815260040161026590610e4a565b60405180910390fd5b6001600160a01b03811660009081526001602052604090205460ff166102c55760405162461bcd60e51b815260206004820152600c60248201526b2737ba10309039b4b3b732b960a11b6044820152606401610265565b6001600160a01b038116600081815260016020526040808220805460ff19169055517f3525e22824a8a7df2c9a6029941c824cf95b6447f1e13d5128fd3826d35afe8b9190a250565b6002546001600160a01b031633146103385760405162461bcd60e51b815260040161026590610e4a565b60008151116103815760405162461bcd60e51b81526020600482015260156024820152741399595908185d081b19585cdd081bdb9948155493605a1b6044820152606401610265565b8051610394906000906020840190610a2b565b507f8420b9370c99306e78c47378a2edbba7a1b63908514191a9db75d654e0b747a6816040516103c49190610de8565b60405180910390a150565b600081815481106103df57600080fd5b9060005260206000200160009150905080546103fa90610e6e565b80601f016020809104026020016040519081016040528092919081815260200182805461042690610e6e565b80156104735780601f1061044857610100808354040283529160200191610473565b820191906000526020600020905b81548152906001019060200180831161045657829003601f168201915b505050505081565b60606000858585856040516020016104969493929190610ea8565b60408051601f1981840301815290829052630556f18360e41b82529150610265903090600090849063b4a8580160e01b908290600401610eca565b6060600080806104e387890189611007565b925092509250428267ffffffffffffffff1610156105365760405162461bcd60e51b815260206004820152601060248201526f14995cdc1bdb9cd948195e1c1a5c995960821b6044820152606401610265565b60008686604051610548929190611084565b604080519182900382208651602080890191909120308286015267ffffffffffffffff8816858501526060850183905260808086018290528451808703909101815260a0860185528051908301207f19457468657265756d205369676e6564204d6573736167653a0a33320000000060c087015260dc8087018290528551808803909101815260fc9096019094528451949091019390932090935060006105ef82876108e6565b6001600160a01b03811660009081526001602052604090205490915060ff1661064b5760405162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21039b4b3b732b960911b6044820152606401610265565b50959b9a5050505050505050505050565b60606000805480602002602001604051908101604052809291908181526020016000905b8282101561072c57838290600052602060002001805461069f90610e6e565b80601f01602080910402602001604051908101604052809291908181526020018280546106cb90610e6e565b80156107185780601f106106ed57610100808354040283529160200191610718565b820191906000526020600020905b8154815290600101906020018083116106fb57829003601f168201915b505050505081526020019060010190610680565b50505050905090565b6002546001600160a01b0316331461075f5760405162461bcd60e51b815260040161026590610e4a565b6001600160a01b0381166107a75760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b6044820152606401610265565b6001600160a01b03811660009081526001602052604090205460ff16156108035760405162461bcd60e51b815260206004820152601060248201526f20b63932b0b23c90309039b4b3b732b960811b6044820152606401610265565b6001600160a01b0381166000818152600160208190526040808320805460ff1916909217909155517f47d1c22a25bb3a5d4e481b9b1e6944c2eade3181a0a20b495ed61d35b5323f249190a250565b6002546001600160a01b0316331461087c5760405162461bcd60e51b815260040161026590610e4a565b6001600160a01b0381166108c45760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b6044820152606401610265565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b600081516041146109395760405162461bcd60e51b815260206004820152601860248201527f496e76616c6964207369676e6174757265206c656e67746800000000000000006044820152606401610265565b60208201516040830151606084015160001a601b8110156109625761095f601b82611094565b90505b8060ff16601b148061097757508060ff16601c145b6109c35760405162461bcd60e51b815260206004820152601960248201527f496e76616c6964207369676e617475726520762076616c7565000000000000006044820152606401610265565b60408051600081526020810180835288905260ff831691810191909152606081018490526080810183905260019060a0016020604051602081039080840390855afa158015610a16573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b828054828255906000526020600020908101928215610a71579160200282015b82811115610a715782518290610a61908261110a565b5091602001919060010190610a4b565b50610a7d929150610a81565b5090565b80821115610a7d576000610a958282610a9e565b50600101610a81565b508054610aaa90610e6e565b6000825580601f10610aba575050565b601f016020900490600052602060002090810190610ad89190610adb565b50565b5b80821115610a7d5760008155600101610adc565b600060208284031215610b0257600080fd5b81356001600160e01b031981168114610b1a57600080fd5b9392505050565b600060208284031215610b3357600080fd5b81356001600160a01b0381168114610b1a57600080fd5b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715610b8957610b89610b4a565b604052919050565b600067ffffffffffffffff831115610bab57610bab610b4a565b610bbe601f8401601f1916602001610b60565b9050828152838383011115610bd257600080fd5b828260208301376000602084830101529392505050565b60006020808385031215610bfc57600080fd5b823567ffffffffffffffff80821115610c1457600080fd5b818501915085601f830112610c2857600080fd5b813581811115610c3a57610c3a610b4a565b8060051b610c49858201610b60565b9182528381018501918581019089841115610c6357600080fd5b86860192505b83831015610cb457823585811115610c815760008081fd5b8601603f81018b13610c935760008081fd5b610ca48b8983013560408401610b91565b8352509186019190860190610c69565b9998505050505050505050565b600060208284031215610cd357600080fd5b5035919050565b6000815180845260005b81811015610d0057602081850181015186830182015201610ce4565b506000602082860101526020601f19601f83011685010191505092915050565b602081526000610b1a6020830184610cda565b60008083601f840112610d4557600080fd5b50813567ffffffffffffffff811115610d5d57600080fd5b602083019150836020828501011115610d7557600080fd5b9250929050565b60008060008060408587031215610d9257600080fd5b843567ffffffffffffffff80821115610daa57600080fd5b610db688838901610d33565b90965094506020870135915080821115610dcf57600080fd5b50610ddc87828801610d33565b95989497509550505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b82811015610e3d57603f19888603018452610e2b858351610cda565b94509285019290850190600101610e0f565b5092979650505050505050565b6020808252600a908201526927b7363c9037bbb732b960b11b604082015260600190565b600181811c90821680610e8257607f821691505b602082108103610ea257634e487b7160e01b600052602260045260246000fd5b50919050565b8385823760008482016000815283858237600093019283525090949350505050565b600060a0820160018060a01b0388168352602060a08185015281885480845260c0860191506005935060c081851b87010160008b8152848120815b84811015610f985760bf198a8503018652828254610f2281610e6e565b80875260018281168015610f3d5760018114610f5657610f81565b60ff198416898d01528215158d1b89018c019450610f81565b8688528b8820885b84811015610f795781548b82018f0152908301908d01610f5e565b8a018d019550505b50988a019892965050509190910190600101610f05565b5050508681036040880152610fad818b610cda565b945050505050610fc960608401866001600160e01b0319169052565b8281036080840152610fdb8185610cda565b98975050505050505050565b600082601f830112610ff857600080fd5b610b1a83833560208501610b91565b60008060006060848603121561101c57600080fd5b833567ffffffffffffffff8082111561103457600080fd5b61104087838801610fe7565b945060208601359150808216821461105757600080fd5b9092506040850135908082111561106d57600080fd5b5061107a86828701610fe7565b9150509250925092565b8183823760009101908152919050565b60ff818116838216019081111561023557634e487b7160e01b600052601160045260246000fd5b601f82111561110557600081815260208120601f850160051c810160208610156110e25750805b601f850160051c820191505b81811015611101578281556001016110ee565b5050505b505050565b815167ffffffffffffffff81111561112457611124610b4a565b611138816111328454610e6e565b846110bb565b602080601f83116001811461116d57600084156111555750858301515b600019600386901b1c1916600185901b178555611101565b600085815260208120601f198616915b8281101561119c5788860151825594840194600190910190840161117d565b50858210156111ba5787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fea2646970667358221220b848651ed822819ddc3c7dec022edb63a724454c75997c03e70189368f362b5c64736f6c63430008110033
Verified Source Code Full Match
Compiler: v0.8.17+commit.8df45f5f
EVM: london
Optimization: Yes (200 runs)
OffchainResolver.sol 267 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
/**
* @title OffchainResolver
* @notice ENS resolver with CCIP-Read offchain resolution support
* @dev Implements EIP-3668 (CCIP-Read) and ENSIP-10 (Wildcard Resolution)
*
* This resolver delegates resolution to an offchain gateway server,
* which returns cryptographically signed responses that are verified onchain.
*
* Features:
* - Offchain resolution via CCIP-Read
* - Multiple authorized signers
* - Wildcard subdomain support
* - Multi-coin address resolution
* - Text records, contenthash, and more
*
* Gateway Response Format:
* {
* "data": "0x...", // ABI-encoded response
* "expires": 123456789, // Unix timestamp
* "sig": "0x..." // EIP-191 signature
* }
*/
/**
* @dev Interface for ENS registry to resolve names
*/
interface IExtendedResolver {
function resolve(bytes calldata name, bytes calldata data)
external
view
returns (bytes memory);
}
contract OffchainResolver is IExtendedResolver {
error OffchainLookup(
address sender,
string[] urls,
bytes callData,
bytes4 callbackFunction,
bytes extraData
);
event SignerAdded(address indexed signer);
event SignerRemoved(address indexed signer);
event UrlUpdated(string[] urls);
string[] public urls;
mapping(address => bool) public signers;
address public owner;
modifier onlyOwner() {
require(msg.sender == owner, "Only owner");
_;
}
/**
* @notice Create a new OffchainResolver
* @param _url Gateway URL template (use {sender} and {data} placeholders)
* @param _signers Array of authorized signer addresses
*
* Example URL: "https://gateway.example.com/{sender}/{data}.json"
*/
constructor(string memory _url, address[] memory _signers) {
owner = msg.sender;
urls = new string[](1);
urls[0] = _url;
for (uint256 i = 0; i < _signers.length; i++) {
signers[_signers[i]] = true;
emit SignerAdded(_signers[i]);
}
emit UrlUpdated(urls);
}
/**
* @notice Main resolution function implementing ENSIP-10 wildcard resolution
* @param name DNS-encoded name (e.g., "\x07vitalik\x03eth\x00")
* @param data ABI-encoded function call (e.g., addr(bytes32))
* @return Resolved data from gateway
*
* This function always reverts with OffchainLookup, triggering CCIP-Read.
* The client then queries the gateway and calls the callback function.
*/
function resolve(bytes calldata name, bytes calldata data)
external
view
returns (bytes memory)
{
// Construct the request for the gateway
bytes memory callData = abi.encodePacked(name, data);
// Revert with OffchainLookup to trigger CCIP-Read
revert OffchainLookup(
address(this), // sender: this contract
urls, // urls: gateway endpoints
callData, // callData: what to send to gateway
this.resolveCallback.selector, // callback function
callData // extraData: passed to callback
);
}
/**
* @notice Callback function called after gateway returns data
* @param response Gateway response (ABI-encoded: bytes data, uint64 expires, bytes sig)
* @param extraData Original request data (for verification)
* @return Resolved data after signature verification
*
* Response format from gateway:
* abi.encode(responseData, expirationTimestamp, signature)
*
* The signature is over: keccak256(abi.encodePacked(
* target (this contract),
* expires (uint64),
* request (original callData),
* result (responseData)
* ))
*/
function resolveCallback(bytes calldata response, bytes calldata extraData)
external
view
returns (bytes memory)
{
// Decode gateway response
(bytes memory responseData, uint64 expires, bytes memory sig) = abi.decode(
response,
(bytes, uint64, bytes)
);
// Check expiration
require(expires >= block.timestamp, "Response expired");
// Verify signature
// Hash the request and result first
bytes32 requestHash = keccak256(extraData);
bytes32 resultHash = keccak256(responseData);
// Create message hash using abi.encode (not encodePacked)
bytes32 messageHash = keccak256(
abi.encode(
address(this), // target
expires, // expires
requestHash, // keccak256(request)
resultHash // keccak256(result)
)
);
// EIP-191 message hash
bytes32 ethSignedMessageHash = keccak256(
abi.encodePacked("\x19Ethereum Signed Message:\n32", messageHash)
);
// Recover signer
address signer = recoverSigner(ethSignedMessageHash, sig);
// Verify signer is authorized
require(signers[signer], "Invalid signer");
return responseData;
}
/**
* @notice Recover signer address from signature
* @param ethSignedMessageHash EIP-191 formatted message hash
* @param sig Signature bytes (65 bytes: r + s + v)
* @return Signer address
*/
function recoverSigner(bytes32 ethSignedMessageHash, bytes memory sig)
internal
pure
returns (address)
{
require(sig.length == 65, "Invalid signature length");
bytes32 r;
bytes32 s;
uint8 v;
assembly {
r := mload(add(sig, 32))
s := mload(add(sig, 64))
v := byte(0, mload(add(sig, 96)))
}
// Adjust v if needed (some libraries use 0/1 instead of 27/28)
if (v < 27) {
v += 27;
}
require(v == 27 || v == 28, "Invalid signature v value");
return ecrecover(ethSignedMessageHash, v, r, s);
}
/**
* @notice Check if address is an authorized signer
* @param _signer Address to check
* @return True if authorized
*/
function isSigner(address _signer) external view returns (bool) {
return signers[_signer];
}
/**
* @notice Add a new authorized signer (owner only)
* @param _signer Address to authorize
*/
function addSigner(address _signer) external onlyOwner {
require(_signer != address(0), "Invalid address");
require(!signers[_signer], "Already a signer");
signers[_signer] = true;
emit SignerAdded(_signer);
}
/**
* @notice Remove an authorized signer (owner only)
* @param _signer Address to remove
*/
function removeSigner(address _signer) external onlyOwner {
require(signers[_signer], "Not a signer");
signers[_signer] = false;
emit SignerRemoved(_signer);
}
/**
* @notice Update gateway URLs (owner only)
* @param _urls New array of gateway URLs
*/
function setUrls(string[] memory _urls) external onlyOwner {
require(_urls.length > 0, "Need at least one URL");
urls = _urls;
emit UrlUpdated(_urls);
}
/**
* @notice Get all gateway URLs
* @return Array of gateway URLs
*/
function getUrls() external view returns (string[] memory) {
return urls;
}
/**
* @notice Transfer ownership
* @param newOwner New owner address
*/
function transferOwnership(address newOwner) external onlyOwner {
require(newOwner != address(0), "Invalid address");
owner = newOwner;
}
/**
* @notice Check if contract supports an interface (EIP-165)
* @param interfaceID Interface identifier
* @return True if supported
*/
function supportsInterface(bytes4 interfaceID) external pure returns (bool) {
return
interfaceID == 0x9061b923 || // IExtendedResolver
interfaceID == 0x01ffc9a7; // EIP-165
}
}
Read Contract
getUrls 0xda06e07f → string[]
isSigner 0x7df73e27 → bool
owner 0x8da5cb5b → address
resolve 0x9061b923 → bytes
resolveCallback 0xb4a85801 → bytes
signers 0x736c0d5b → bool
supportsInterface 0x01ffc9a7 → bool
urls 0x796676be → string
Write Contract 4 functions
These functions modify contract state and require a wallet transaction to execute.
addSigner 0xeb12d61e
address _signer
removeSigner 0x0e316ab7
address _signer
setUrls 0x6cc895a9
string[] _urls
transferOwnership 0xf2fde38b
address newOwner
Recent Transactions
No transactions found for this address