账户
0x2f...cca9
0x2F...cca9

0x2F...cca9

$500
此合同的源代码已经过验证!
合同元数据
编译器
0.8.25+commit.b61c2a91
语言
Solidity
合同源代码
文件 1 的 1:UnruggableMappingsResolver.sol
// SPDX-License-Identifier: MIT
// Resolver contract for ENS that allows for the setting of addresses and text records for both specified and wildcard resolution.
// This contract implements the resolution interfaces defined in ENSIP-1, ENSIP-5, ENSIP-9 and ENSIP-10.
// Built by clowes.eth for Unruggable
// 13th September 2024
// Across the contract coinType is as defined in ENSIP-11 https://docs.ens.domains/ensip/11
pragma solidity ^0.8.25;

contract UnruggableMappingsResolver {

    //ENSIP-1 - https://docs.ens.domains/ensip/1
    event AddrChanged(bytes32 indexed node, address a);
    //ENSIP-9 - https://docs.ens.domains/ensip/9
    event AddressChanged(bytes32 indexed node, uint coinType, bytes newAddress);

    //Not standardised => https://docs.ens.domains/resolvers/interfaces
    event TextChanged(
        bytes32 indexed node,
        string indexed indexedKey,
        string key,
        string value
    );

    address owner;
    mapping(bytes32 node => mapping(uint256 coinType => bytes resolutionAddress)) private namehashToAddress;
    mapping(bytes32 node => bool isDisabled) private disableEthDefault;
    mapping(bytes32 node => mapping(string key => string value)) private textMapping;

    uint constant private COIN_TYPE_ETH = 60;

    // ERC-165 => Standard Interface Detection
    // supportsInterface(bytes4)
    bytes4 constant private INTERFACE_ID_ERC_165 = 0x01ffc9a7;

    // The addr Interface defined in ENSIP-1 => ENS
    // addr(bytes32 node)
    bytes4 constant private INTERFACE_ID_ADDR = 0x3b3b57de;

    // ENSIP-9 => Multichain Address resolution
    // addr(bytes32 node, uint coinType)
    // https://ethtools.com/interface-database/ENSIP-9
    bytes4 constant private INTERFACE_ID_ADDR_ENSIP_9 = 0xf1cb7e06;

    // ENSIP-10 => Wildcard Resolution
    // resolve(bytes calldata name, bytes calldata data) external view returns(bytes)
    // https://ethtools.com/interface-database/IExtendedResolver
    bytes4 constant private INTERFACE_ID_ENSIP_10 = 0x9061b923;

    // ENSIP-5 => Text Records
    // text(bytes32 node, string calldata key)
    // https://ethtools.com/interface-database/ENSIP-5
    bytes4 constant private INTERFACE_ID_TEXT = 0x59d1d43c;

    modifier onlyOwner() {
        require(msg.sender == owner, "Unauthorized");
        _;
    }

    constructor() {
        owner = msg.sender;
    }

    /**
     * Implemented as part of the ERC165 interface => Standard Interface Detection
     * https://ethtools.com/interface-database/ERC165
     * https://eips.ethereum.org/EIPS/eip-165
     */
    function supportsInterface(bytes4 interfaceID) external pure returns (bool) {
		return interfaceID == INTERFACE_ID_ADDR 
        || interfaceID == INTERFACE_ID_ADDR_ENSIP_9 
        || interfaceID == INTERFACE_ID_ERC_165 
        || interfaceID == INTERFACE_ID_ENSIP_10
        || interfaceID == INTERFACE_ID_TEXT;       
	}
 
     /*************
      ** Setters **
      *************/

    function setAddr(bytes32 node, address addr) public onlyOwner {
        setAddr(node, addr, COIN_TYPE_ETH);
        emit AddrChanged(node, addr);
    }

    function setAddr(bytes32 node, address addr, uint coinType) public onlyOwner {
        namehashToAddress[node][coinType] = addressToBytes(addr);
        emit AddressChanged(node, coinType, namehashToAddress[node][coinType]);
    }

    function setAddr(bytes32 node, address addr, uint[] calldata coinTypes) public onlyOwner {
        for (uint i = 0; i < coinTypes.length; i++) {
            setAddr(node, addr, coinTypes[i]);
        }
    }

    function setText(bytes32 node, string memory key, string memory value) public onlyOwner {
        textMapping[node][key] = value;
        emit TextChanged(node, key, key, value);
    }

    function setIsEthDefaultDisabled(bytes32 node, bool isIt) public onlyOwner {
        disableEthDefault[node] = isIt;
    }


    /*************
     ** Getters **
     *************/

    /**
     * Implemented as part of the addr interface defined in ENSIP-1 => ENS
     * ENSIP-1 - https://docs.ens.domains/ensip/1
     * https://ethtools.com/interface-database/ENSIP-1-addr
     */
    function addr(bytes32 node) public view returns (address) {
        bytes memory a = addr(node, COIN_TYPE_ETH);

        if(a.length == 0) {
            return address(0);
        }

        return bytesToAddress(a);
	}

    /**
     * Implemented as part of the interface defined in ENSIP-9 => Multichain Address resolution
     * ENSIP-9 - https://docs.ens.domains/ensip/9 AND ENSIP-11 - https://docs.ens.domains/ensip/11
     * https://ethtools.com/interface-database/ENSIP-9
     */
    function addr(bytes32 node, uint coinType) public view returns (bytes memory) {
        bytes memory specifiedAddress = namehashToAddress[node][coinType];

        if (specifiedAddress.length == 0) {
            if (coinType != COIN_TYPE_ETH && !disableEthDefault[node]) {
                specifiedAddress = namehashToAddress[node][COIN_TYPE_ETH];
            }
        }

        return specifiedAddress;     
    }


    /**
     * Implemented as part of the interface specification defined in ENSIP-5 => Text Records
     * ENSIP-5 - https://docs.ens.domains/ensip/5 and ENSIP-18 - https://docs.ens.domains/ensip/18
     * https://ethtools.com/interface-database/ENSIP-5
     */
    function text(
        bytes32 node,
        string memory key
    ) public view returns (string memory) {
        return textMapping[node][key];
    }

    /**
     * Implemented as part of the IExtendedResolver interface defined in ENSIP-10 => Wildcard Resolution
     * https://ethtools.com/interface-database/IExtendedResolver
     * ENSIP-10 - https://docs.ens.domains/ensip/10
     */
    function resolve(bytes calldata name, bytes calldata data) external view returns(bytes memory) {

        bytes4 selector = bytes4(data[:4]);

        //These interfaces only have one method so interface ID === selector ID
        if (selector == INTERFACE_ID_ADDR) {
            (bytes32 node) = abi.decode(data[4:], (bytes32));   
            return abi.encode(addr(node));
        } else if (selector == INTERFACE_ID_ADDR_ENSIP_9) {
            (bytes32 node, uint256 coinType) = abi.decode(data[4:], (bytes32, uint256));   
            return abi.encode(addr(node, coinType));
        } else if (selector == INTERFACE_ID_TEXT) {                 
            (bytes32 node, string memory key) = abi.decode(data[4:], (bytes32, string));   
            string memory value = text(node, key);
            return abi.encode(value);
        }

        revert("Unsupported");
    }

    /*************
     ** Helpers **
     *************/

    function bytesToAddress(bytes memory b) internal pure returns(address payable a) {
        require(b.length == 20);
        assembly {
            a := div(mload(add(b, 32)), exp(256, 12))
        }
    }

    function addressToBytes(address a) internal pure returns(bytes memory b) {
        b = new bytes(20);
        assembly {
            mstore(add(b, 32), mul(a, exp(256, 12)))
        }
    }
}
设置
{
  "compilationTarget": {
    "contracts/UnruggableMappingsResolver.sol": "UnruggableMappingsResolver"
  },
  "evmVersion": "paris",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "remappings": [
    ":@eth-optimism/=lib/unruggable-gateways/lib/optimism/packages/",
    ":@openzeppelin/contracts/=lib/unruggable-gateways/lib/openzeppelin-contracts/contracts/",
    ":@unruggable/=lib/unruggable-gateways/",
    ":ds-test/=lib/unruggable-gateways/lib/openzeppelin-contracts/lib/forge-std/lib/ds-test/src/",
    ":erc4626-tests/=lib/unruggable-gateways/lib/openzeppelin-contracts/lib/erc4626-tests/",
    ":forge-std/=lib/unruggable-gateways/lib/forge-std/src/",
    ":openzeppelin-contracts/=lib/unruggable-gateways/lib/openzeppelin-contracts/",
    ":optimism/=lib/unruggable-gateways/lib/optimism/packages/contracts-bedrock/src/",
    ":unruggable-gateways/=lib/unruggable-gateways/contracts/"
  ]
}
ABI
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"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":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","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"coinType","type":"uint256"}],"name":"addr","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"name","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":"address","name":"addr","type":"address"},{"internalType":"uint256[]","name":"coinTypes","type":"uint256[]"}],"name":"setAddr","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"address","name":"addr","type":"address"}],"name":"setAddr","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"coinType","type":"uint256"}],"name":"setAddr","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bool","name":"isIt","type":"bool"}],"name":"setIsEthDefaultDisabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"key","type":"string"},{"internalType":"string","name":"value","type":"string"}],"name":"setText","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceID","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"key","type":"string"}],"name":"text","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]