编译器
0.8.24+commit.e11b9ed9
文件 1 的 15:BytesUtils.sol
pragma solidity ~0.8.17;
library BytesUtils {
function keccak(
bytes memory self,
uint256 offset,
uint256 len
) internal pure returns (bytes32 ret) {
require(offset + len <= self.length);
assembly {
ret := keccak256(add(add(self, 32), offset), len)
}
}
function namehash(
bytes memory self,
uint256 offset
) internal pure returns (bytes32) {
(bytes32 labelhash, uint256 newOffset) = readLabel(self, offset);
if (labelhash == bytes32(0)) {
require(offset == self.length - 1, "namehash: Junk at end of name");
return bytes32(0);
}
return
keccak256(abi.encodePacked(namehash(self, newOffset), labelhash));
}
function readLabel(
bytes memory self,
uint256 idx
) internal pure returns (bytes32 labelhash, uint256 newIdx) {
require(idx < self.length, "readLabel: Index out of bounds");
uint256 len = uint256(uint8(self[idx]));
if (len > 0) {
labelhash = keccak(self, idx + 1, len);
} else {
labelhash = bytes32(0);
}
newIdx = idx + len + 1;
}
}
文件 2 的 15:ECDSA.sol
pragma solidity ^0.8.20;
library ECDSA {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS
}
error ECDSAInvalidSignature();
error ECDSAInvalidSignatureLength(uint256 length);
error ECDSAInvalidSignatureS(bytes32 s);
function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError, bytes32) {
if (signature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return tryRecover(hash, v, r, s);
} else {
return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length));
}
}
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature);
_throwError(error, errorArg);
return recovered;
}
function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError, bytes32) {
unchecked {
bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
uint8 v = uint8((uint256(vs) >> 255) + 27);
return tryRecover(hash, v, r, s);
}
}
function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs);
_throwError(error, errorArg);
return recovered;
}
function tryRecover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address, RecoverError, bytes32) {
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS, s);
}
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature, bytes32(0));
}
return (signer, RecoverError.NoError, bytes32(0));
}
function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s);
_throwError(error, errorArg);
return recovered;
}
function _throwError(RecoverError error, bytes32 errorArg) private pure {
if (error == RecoverError.NoError) {
return;
} else if (error == RecoverError.InvalidSignature) {
revert ECDSAInvalidSignature();
} else if (error == RecoverError.InvalidSignatureLength) {
revert ECDSAInvalidSignatureLength(uint256(errorArg));
} else if (error == RecoverError.InvalidSignatureS) {
revert ECDSAInvalidSignatureS(errorArg);
}
}
}
文件 3 的 15:ENS.sol
pragma solidity >=0.8.4;
interface ENS {
event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);
event Transfer(bytes32 indexed node, address owner);
event NewResolver(bytes32 indexed node, address resolver);
event NewTTL(bytes32 indexed node, uint64 ttl);
event ApprovalForAll(
address indexed owner,
address indexed operator,
bool approved
);
function setRecord(
bytes32 node,
address owner,
address resolver,
uint64 ttl
) external;
function setSubnodeRecord(
bytes32 node,
bytes32 label,
address owner,
address resolver,
uint64 ttl
) external;
function setSubnodeOwner(
bytes32 node,
bytes32 label,
address owner
) external returns (bytes32);
function setResolver(bytes32 node, address resolver) external;
function setOwner(bytes32 node, address owner) external;
function setTTL(bytes32 node, uint64 ttl) external;
function setApprovalForAll(address operator, bool approved) external;
function owner(bytes32 node) external view returns (address);
function resolver(bytes32 node) external view returns (address);
function ttl(bytes32 node) external view returns (uint64);
function recordExists(bytes32 node) external view returns (bool);
function isApprovedForAll(
address owner,
address operator
) external view returns (bool);
}
文件 4 的 15:HexUtils.sol
pragma solidity ^0.8.4;
library HexUtils {
function hexStringToBytes32(
bytes memory str,
uint256 idx,
uint256 lastIdx
) internal pure returns (bytes32 r, bool valid) {
uint256 hexLength = lastIdx - idx;
if ((hexLength != 64 && hexLength != 40) || hexLength % 2 == 1) {
revert("Invalid string length");
}
valid = true;
assembly {
if gt(lastIdx, mload(str)) {
revert(0, 0)
}
function getHex(c) -> ascii {
if and(gt(c, 47), lt(c, 58)) {
ascii := sub(c, 48)
leave
}
if and(gt(c, 64), lt(c, 71)) {
ascii := add(sub(c, 65), 10)
leave
}
if and(gt(c, 96), lt(c, 103)) {
ascii := add(sub(c, 97), 10)
leave
}
ascii := 0xff
}
let ptr := add(str, 32)
for {
let i := idx
} lt(i, lastIdx) {
i := add(i, 2)
} {
let byte1 := getHex(byte(0, mload(add(ptr, i))))
let byte2 := getHex(byte(0, mload(add(ptr, add(i, 1)))))
if or(eq(byte1, 0xff), eq(byte2, 0xff)) {
valid := false
break
}
let combined := or(shl(4, byte1), byte2)
r := or(shl(8, r), combined)
}
}
}
function hexToAddress(
bytes memory str,
uint256 idx,
uint256 lastIdx
) internal pure returns (address, bool) {
if (lastIdx - idx < 40) return (address(0x0), false);
(bytes32 r, bool valid) = hexStringToBytes32(str, idx, lastIdx);
return (address(uint160(uint256(r))), valid);
}
}
文件 5 的 15:IAddrResolver.sol
pragma solidity >=0.8.4;
interface IAddrResolver {
event AddrChanged(bytes32 indexed node, address a);
function addr(bytes32 node) external view returns (address payable);
}
文件 6 的 15:IAddressResolver.sol
pragma solidity >=0.8.4;
interface IAddressResolver {
event AddressChanged(
bytes32 indexed node,
uint256 coinType,
bytes newAddress
);
function addr(
bytes32 node,
uint256 coinType
) external view returns (bytes memory);
}
文件 7 的 15:IContentHashResolver.sol
pragma solidity >=0.8.4;
interface IContentHashResolver {
event ContenthashChanged(bytes32 indexed node, bytes hash);
function contenthash(bytes32 node) external view returns (bytes memory);
}
文件 8 的 15:IERC165.sol
pragma solidity ^0.8.20;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 9 的 15:IExtendedDNSResolver.sol
pragma solidity ^0.8.4;
interface IExtendedDNSResolver {
function resolve(
bytes memory name,
bytes memory data,
bytes memory context
) external view returns (bytes memory);
}
文件 10 的 15:IExtendedResolver.sol
pragma solidity ^0.8.4;
interface IExtendedResolver {
function resolve(
bytes memory name,
bytes memory data
) external view returns (bytes memory);
}
文件 11 的 15:IMulticallable.sol
pragma solidity ^0.8.4;
interface IMulticallable {
function multicall(
bytes[] calldata data
) external returns (bytes[] memory results);
function multicallWithNodeCheck(
bytes32,
bytes[] calldata data
) external returns (bytes[] memory results);
}
文件 12 的 15:INameResolver.sol
pragma solidity >=0.8.4;
interface INameResolver {
event NameChanged(bytes32 indexed node, string name);
function name(bytes32 node) external view returns (string memory);
}
文件 13 的 15:IPubkeyResolver.sol
pragma solidity >=0.8.4;
interface IPubkeyResolver {
event PubkeyChanged(bytes32 indexed node, bytes32 x, bytes32 y);
function pubkey(bytes32 node) external view returns (bytes32 x, bytes32 y);
}
文件 14 的 15:ITextResolver.sol
pragma solidity >=0.8.4;
interface ITextResolver {
event TextChanged(
bytes32 indexed node,
string indexed indexedKey,
string key,
string value
);
function text(
bytes32 node,
string calldata key
) external view returns (string memory);
}
文件 15 的 15:TOR.sol
pragma solidity ^0.8.23;
import {ENS} from "@ensdomains/ens-contracts/contracts/registry/ENS.sol";
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import {IExtendedResolver} from "@ensdomains/ens-contracts/contracts/resolvers/profiles/IExtendedResolver.sol";
import {IExtendedDNSResolver} from "@ensdomains/ens-contracts/contracts/resolvers/profiles/IExtendedDNSResolver.sol";
import {IAddrResolver} from "@ensdomains/ens-contracts/contracts/resolvers/profiles/IAddrResolver.sol";
import {IAddressResolver} from "@ensdomains/ens-contracts/contracts/resolvers/profiles/IAddressResolver.sol";
import {ITextResolver} from "@ensdomains/ens-contracts/contracts/resolvers/profiles/ITextResolver.sol";
import {INameResolver} from "@ensdomains/ens-contracts/contracts/resolvers/profiles/INameResolver.sol";
import {IPubkeyResolver} from "@ensdomains/ens-contracts/contracts/resolvers/profiles/IPubkeyResolver.sol";
import {IContentHashResolver} from "@ensdomains/ens-contracts/contracts/resolvers/profiles/IContentHashResolver.sol";
import {IMulticallable} from "@ensdomains/ens-contracts/contracts/resolvers/IMulticallable.sol";
import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import {BytesUtils} from "@ensdomains/ens-contracts/contracts/wrapper/BytesUtils.sol";
import {HexUtils} from "@ensdomains/ens-contracts/contracts/utils/HexUtils.sol";
error OffchainLookup(address from, string[] urls, bytes request, bytes4 callback, bytes carry);
interface IOnchainResolver {
function onchain(bytes32 node) external view returns (bool);
event OnchainChanged(bytes32 indexed node, bool on);
}
contract TOR is IERC165, ITextResolver, IAddrResolver, IAddressResolver, IPubkeyResolver, IContentHashResolver,
IMulticallable, IExtendedResolver, IExtendedDNSResolver, IOnchainResolver, INameResolver {
using BytesUtils for bytes;
using HexUtils for bytes;
error Unauthorized(address owner);
error InvalidContext(bytes context);
error Unreachable(bytes name);
error CCIPReadExpired(uint256 t);
error CCIPReadUntrusted(address signed, address expect);
error NodeCheck(bytes32 node);
uint256 constant COIN_TYPE_ETH = 60;
uint256 constant COIN_TYPE_FALLBACK = 0xb32cdf4d3c016cb0f079f205ad61c36b1a837fb3e95c70a94bdedfca0518a010;
string constant TEXT_CONTEXT = "ccip.context";
bool constant REPLACE_WITH_ONCHAIN = true;
bool constant OFFCHAIN_ONLY = false;
bool constant CALL_WITH_NULL_NODE = true;
bool constant CALL_UNMODIFIED = false;
bytes4 constant PREFIX_ONLY_OFF = 0x000000FF;
bytes4 constant PREFIX_ONLY_ON = ~PREFIX_ONLY_OFF;
uint256 constant ERC165_GAS_LIMIT = 30000;
ENS immutable ens;
constructor(ENS a) {
ens = a;
}
function supportsInterface(bytes4 x) external pure returns (bool) {
return x == type(IERC165).interfaceId
|| x == type(ITextResolver).interfaceId
|| x == type(IAddrResolver).interfaceId
|| x == type(IAddressResolver).interfaceId
|| x == type(IPubkeyResolver).interfaceId
|| x == type(IContentHashResolver).interfaceId
|| x == type(INameResolver).interfaceId
|| x == type(IMulticallable).interfaceId
|| x == type(IExtendedResolver).interfaceId
|| x == type(IExtendedDNSResolver).interfaceId
|| x == type(IOnchainResolver).interfaceId
|| x == 0x73302a25;
}
modifier requireOperator(bytes32 node) {
address owner = ens.owner(node);
if (owner != msg.sender && !ens.isApprovedForAll(owner, msg.sender)) revert Unauthorized(owner);
_;
}
function slotForCoin(bytes32 node, uint256 cty) internal pure returns (uint256) {
return uint256(keccak256(abi.encodeCall(IAddressResolver.addr, (node, cty))));
}
function slotForText(bytes32 node, string memory key) internal pure returns (uint256) {
return uint256(keccak256(abi.encodeCall(ITextResolver.text, (node, key))));
}
function slotForSelector(bytes4 selector, bytes32 node) internal pure returns (uint256) {
return uint256(keccak256(abi.encodeWithSelector(selector, node)));
}
function addr(bytes32 node) external view returns (address payable a) {
(bytes32 extnode, address resolver) = determineExternalFallback(node);
if (resolver != address(0) && IERC165(resolver).supportsInterface{gas: ERC165_GAS_LIMIT}(type(IAddrResolver).interfaceId)) {
a = IAddrResolver(resolver).addr(extnode);
}
if (a == address(0)) {
a = payable(address(bytes20(getTiny(slotForCoin(node, COIN_TYPE_ETH)))));
}
}
function pubkey(bytes32 node) external view returns (bytes32 x, bytes32 y) {
(bytes32 extnode, address resolver) = determineExternalFallback(node);
if (resolver != address(0) && IERC165(resolver).supportsInterface{gas: ERC165_GAS_LIMIT}(type(IPubkeyResolver).interfaceId)) {
(x, y) = IPubkeyResolver(resolver).pubkey(extnode);
}
if (x == 0 && y == 0) {
bytes memory v = getTiny(slotForSelector(IPubkeyResolver.pubkey.selector, node));
if (v.length == 64) (x, y) = abi.decode(v, (bytes32, bytes32));
}
}
function addr(bytes32, uint256) external view returns (bytes memory) {
return reflectGetBytes(msg.data);
}
function text(bytes32, string calldata) external view returns (string memory) {
return string(reflectGetBytes(msg.data));
}
function contenthash(bytes32) external view returns (bytes memory) {
return reflectGetBytes(msg.data);
}
function name(bytes32) external view returns (string memory) {
return string(reflectGetBytes(msg.data));
}
function reflectGetBytes(bytes memory request) internal view returns (bytes memory v) {
bytes32 node;
assembly { node := mload(add(request, 36)) }
uint256 slot = uint256(keccak256(request));
v = getTiny(slot);
if (v.length == 0) {
(bytes32 extnode, address resolver) = determineExternalFallback(node);
if (resolver != address(0)) {
assembly { mstore(add(request, 36), extnode) }
(bool ok, bytes memory u) = resolver.staticcall(request);
if (ok) {
v = abi.decode(u, (bytes));
}
}
}
}
function parseContext(bytes memory v) internal pure returns (string[] memory urls, address signer) {
if (v.length < 51) revert InvalidContext(v);
bool valid;
(signer, valid) = v.hexToAddress(2, 42);
if (!valid) revert InvalidContext(v);
assembly {
let size := mload(v)
v := add(v, 43)
mstore(v, sub(size, 43))
}
urls = new string[](1);
urls[0] = string(v);
}
function verifyOffchain(bytes calldata ccip, bytes memory carry) internal view returns (bytes memory request, bytes memory response, bool replace) {
bytes memory sig;
uint64 expires;
(sig, expires, response) = abi.decode(ccip, (bytes, uint64, bytes));
if (expires < block.timestamp) revert CCIPReadExpired(expires);
address signer;
(request, signer, replace) = abi.decode(carry, (bytes, address, bool));
bytes32 hash = keccak256(abi.encodePacked(address(this), expires, keccak256(request), keccak256(response)));
address signed = ECDSA.recover(hash, sig);
if (signed != signer) revert CCIPReadUntrusted(signed, signer);
}
function resolve(bytes calldata dnsname, bytes calldata data, bytes calldata context) external view returns (bytes memory) {
(string[] memory urls, address signer) = parseContext(context);
bytes memory request = abi.encodeWithSelector(IExtendedResolver.resolve.selector, dnsname, data);
revert OffchainLookup(address(this), urls, request, this.buggedCallback.selector, abi.encode(abi.encode(request, signer, false), address(this)));
}
function buggedCallback(bytes calldata response, bytes calldata buggedExtraData) external view returns (bytes memory v) {
(, v, ) = verifyOffchain(response, abi.decode(buggedExtraData, (bytes)));
}
function resolve(bytes calldata dnsname, bytes calldata data) external view returns (bytes memory) {
unchecked {
bytes32 node = dnsname.namehash(0);
if (bytes4(data) == PREFIX_ONLY_ON) {
return resolveOnchain(data[4:], CALL_UNMODIFIED);
} else if (bytes4(data) == PREFIX_ONLY_OFF) {
if (onchain(node)) {
return resolveOnchain(data[4:], CALL_WITH_NULL_NODE);
} else {
resolveOffchain(dnsname, data[4:], OFFCHAIN_ONLY);
}
} else if (onchain(node)) {
return resolveOnchain(data, CALL_UNMODIFIED);
} else {
if (bytes4(data) == IMulticallable.multicall.selector) {
bytes[] memory a = abi.decode(data[4:], (bytes[]));
bytes[] memory b = new bytes[](a.length);
for (uint256 i; i < a.length; i += 1) {
bytes memory v = getEncodedFallbackValue(a[i]);
if (v.length == 0) resolveOffchain(dnsname, data, REPLACE_WITH_ONCHAIN);
b[i] = v;
}
return abi.encode(b);
} else {
bytes memory v = getEncodedFallbackValue(data);
if (v.length != 0) return v;
resolveOffchain(dnsname, data, OFFCHAIN_ONLY);
}
}
}
}
function resolveOnchain(bytes calldata data, bool clear) internal view returns (bytes memory result) {
if (bytes4(data) == IMulticallable.multicall.selector) {
bytes[] memory a = abi.decode(data[4:], (bytes[]));
for (uint256 i; i < a.length; i += 1) {
bytes memory v = a[i];
if (clear) assembly { mstore(add(v, 36), 0) }
(, a[i]) = address(this).staticcall(v);
}
result = abi.encode(a);
} else {
bytes memory v = data;
if (clear) assembly { mstore(add(v, 36), 0) }
(, result) = address(this).staticcall(v);
}
}
function resolveOffchain(bytes calldata dnsname, bytes calldata data, bool replace) internal view {
(string[] memory urls, address signer) = parseContext(findContext(dnsname));
bytes memory request = abi.encodeWithSelector(IExtendedResolver.resolve.selector, dnsname, data);
revert OffchainLookup(address(this), urls, request, this.ensCallback.selector, abi.encode(request, signer, replace));
}
function findContext(bytes calldata dnsname) internal view returns (bytes memory context) {
unchecked {
uint256 offset;
while (true) {
bytes32 node = dnsname.namehash(offset);
if (ens.resolver(node) == address(this)) {
context = getTiny(slotForText(node, TEXT_CONTEXT));
if (context.length != 0) break;
}
uint256 size = uint256(uint8(dnsname[offset]));
if (size == 0) revert Unreachable(dnsname);
offset += 1 + size;
}
}
}
function ensCallback(bytes calldata ccip, bytes calldata carry) external view returns (bytes memory) {
unchecked {
(bytes memory request, bytes memory response, bool replace) = verifyOffchain(ccip, carry);
if (!replace) return response;
assembly {
mstore(add(request, 4), sub(mload(request), 4))
request := add(request, 4)
}
(, request) = abi.decode(request, (bytes, bytes));
assembly {
mstore(add(request, 4), sub(mload(request), 4))
request := add(request, 4)
}
bytes[] memory a = abi.decode(request, (bytes[]));
bytes[] memory b = abi.decode(response, (bytes[]));
for (uint256 i; i < a.length; i += 1) {
bytes memory v = getEncodedFallbackValue(a[i]);
if (v.length != 0) b[i] = v;
}
return abi.encode(b);
}
}
function determineExternalFallback(bytes32 node) internal view returns (bytes32 extnode, address resolver) {
bytes memory v = getTiny(slotForCoin(node, COIN_TYPE_FALLBACK));
if (v.length == 20) {
extnode = node;
resolver = address(bytes20(v));
} else {
if (v.length == 32) {
extnode = bytes32(v);
} else if (v.length != 0) {
} else {
extnode = keccak256(abi.encode(node, 0xcd5edcba1904ce1b09e94c8a2d2a85375599856ca21c793571193054498b51d7));
}
resolver = ens.resolver(extnode);
}
}
function getEncodedFallbackValue(bytes memory request) internal view returns (bytes memory encoded) {
(bool ok, bytes memory v) = address(this).staticcall(request);
if (ok && !isNullAssumingPadded(v)) {
if (keccak256(v) != 0x569e75fc77c1a856f6daaf9e69d8a9566ca34aa47f9133711ce065a571af0cfd) {
encoded = v;
}
}
}
function isNullAssumingPadded(bytes memory v) internal pure returns (bool ret) {
assembly {
let p := add(v, 32)
let e := add(p, mload(v))
for { ret := 1 } lt(p, e) { p := add(p, 32) } {
if iszero(iszero(mload(p))) {
ret := 0
break
}
}
}
}
function multicall(bytes[] calldata calls) external returns (bytes[] memory) {
return _multicall(0, calls);
}
function multicallWithNodeCheck(bytes32 nodehash, bytes[] calldata calls) external returns (bytes[] memory) {
return _multicall(nodehash, calls);
}
function _multicall(bytes32 node, bytes[] calldata calls) internal returns (bytes[] memory answers) {
unchecked {
answers = new bytes[](calls.length);
for (uint256 i; i < calls.length; i += 1) {
if (node != 0) {
bytes32 check = bytes32(calls[i][4:36]);
if (check != node) revert NodeCheck(check);
}
(bool ok, bytes memory v) = address(this).delegatecall(calls[i]);
require(ok);
answers[i] = v;
}
}
}
function setAddr(bytes32 node, address a) external {
setAddr(node, COIN_TYPE_ETH, a == address(0) ? bytes('') : abi.encodePacked(a));
}
function setAddr(bytes32 node, uint256 cty, bytes memory v) requireOperator(node) public {
setTiny(slotForCoin(node, cty), v);
emit AddressChanged(node, cty, v);
if (cty == COIN_TYPE_ETH) emit AddrChanged(node, address(bytes20(v)));
}
function setText(bytes32 node, string calldata key, string calldata s) requireOperator(node) external {
setTiny(slotForText(node, key), bytes(s));
emit TextChanged(node, key, key, s);
}
function setContenthash(bytes32 node, bytes calldata v) requireOperator(node) external {
setTiny(slotForSelector(IContentHashResolver.contenthash.selector, node), v);
emit ContenthashChanged(node, v);
}
function setPubkey(bytes32 node, bytes32 x, bytes32 y) requireOperator(node) external {
setTiny(slotForSelector(IPubkeyResolver.pubkey.selector, node), x == 0 && y == 0 ? bytes('') : abi.encode(x, y));
emit PubkeyChanged(node, x, y);
}
function toggleOnchain(bytes32 node) requireOperator(node) external {
uint256 slot = slotForSelector(IOnchainResolver.onchain.selector, node);
bool on;
assembly {
on := iszero(sload(slot))
sstore(slot, on)
}
emit OnchainChanged(node, on);
}
function onchain(bytes32 node) public view returns (bool) {
uint256 slot = slotForSelector(IOnchainResolver.onchain.selector, node);
assembly { slot := sload(slot) }
return slot != 0;
}
function tinySlots(uint256 size) internal pure returns (uint256) {
unchecked {
return size != 0 ? (size + 35) >> 5 : 0;
}
}
function setTiny(uint256 slot, bytes memory v) internal {
unchecked {
uint256 head;
assembly { head := sload(slot) }
uint256 size;
assembly { size := mload(v) }
uint256 n0 = tinySlots(head >> 224);
uint256 n1 = tinySlots(size);
assembly {
if gt(n1, 0) {
sstore(slot, or(shl(224, size), shr(32, mload(add(v, 32)))))
let ptr := add(v, 60)
for { let i := 1 } lt(i, n1) { i := add(i, 1) } {
sstore(add(slot, i), mload(ptr))
ptr := add(ptr, 32)
}
}
for { let i := n1 } lt(i, n0) { i := add(i, 1) } {
sstore(add(slot, i), 0)
}
}
}
}
function getTiny(uint256 slot) internal view returns (bytes memory v) {
unchecked {
uint256 head;
assembly { head := sload(slot) }
uint256 size = head >> 224;
if (size != 0) {
v = new bytes(size);
uint256 n = tinySlots(size);
assembly {
mstore(add(v, 32), shl(32, head))
let p := add(v, 60)
for { let i := 1 } lt(i, n) { i := add(i, 1) } {
mstore(p, sload(add(slot, i)))
p := add(p, 32)
}
}
}
}
}
}
{
"compilationTarget": {
"github/resolverworks/TheOffchainResolver.sol/src/TOR.sol": "TOR"
},
"evmVersion": "shanghai",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"contract ENS","name":"a","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"t","type":"uint256"}],"name":"CCIPReadExpired","type":"error"},{"inputs":[{"internalType":"address","name":"signed","type":"address"},{"internalType":"address","name":"expect","type":"address"}],"name":"CCIPReadUntrusted","type":"error"},{"inputs":[],"name":"ECDSAInvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"ECDSAInvalidSignatureLength","type":"error"},{"inputs":[{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ECDSAInvalidSignatureS","type":"error"},{"inputs":[{"internalType":"bytes","name":"context","type":"bytes"}],"name":"InvalidContext","type":"error"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"NodeCheck","type":"error"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"string[]","name":"urls","type":"string[]"},{"internalType":"bytes","name":"request","type":"bytes"},{"internalType":"bytes4","name":"callback","type":"bytes4"},{"internalType":"bytes","name":"carry","type":"bytes"}],"name":"OffchainLookup","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"Unauthorized","type":"error"},{"inputs":[{"internalType":"bytes","name":"name","type":"bytes"}],"name":"Unreachable","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"address","name":"a","type":"address"}],"name":"AddrChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"coinType","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"newAddress","type":"bytes"}],"name":"AddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"hash","type":"bytes"}],"name":"ContenthashChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"string","name":"name","type":"string"}],"name":"NameChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bool","name":"on","type":"bool"}],"name":"OnchainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"x","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"y","type":"bytes32"}],"name":"PubkeyChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"string","name":"indexedKey","type":"string"},{"indexed":false,"internalType":"string","name":"key","type":"string"},{"indexed":false,"internalType":"string","name":"value","type":"string"}],"name":"TextChanged","type":"event"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"addr","outputs":[{"internalType":"address payable","name":"a","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"addr","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"response","type":"bytes"},{"internalType":"bytes","name":"buggedExtraData","type":"bytes"}],"name":"buggedCallback","outputs":[{"internalType":"bytes","name":"v","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"contenthash","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"ccip","type":"bytes"},{"internalType":"bytes","name":"carry","type":"bytes"}],"name":"ensCallback","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"calls","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"","type":"bytes[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"nodehash","type":"bytes32"},{"internalType":"bytes[]","name":"calls","type":"bytes[]"}],"name":"multicallWithNodeCheck","outputs":[{"internalType":"bytes[]","name":"","type":"bytes[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"onchain","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"pubkey","outputs":[{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"dnsname","type":"bytes"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes","name":"context","type":"bytes"}],"name":"resolve","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"dnsname","type":"bytes"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"resolve","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"cty","type":"uint256"},{"internalType":"bytes","name":"v","type":"bytes"}],"name":"setAddr","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"address","name":"a","type":"address"}],"name":"setAddr","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes","name":"v","type":"bytes"}],"name":"setContenthash","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"name":"setPubkey","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"key","type":"string"},{"internalType":"string","name":"s","type":"string"}],"name":"setText","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"x","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"string","name":"","type":"string"}],"name":"text","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"toggleOnchain","outputs":[],"stateMutability":"nonpayable","type":"function"}]