Forkchoice Ethereum Mainnet

Address Contract Verified

Address 0x2FADC853eCC103ecdC61877017Fb72D711789c95
Balance 0 ETH
Nonce 1
Code Size 4163 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

4163 bytes
0x608060405234801561000f575f5ffd5b506004361061004a575f3560e01c806352ef6b2c1461004e5780637a0ed6271461006c578063adfca15e1461008a578063cdffacc6146100ba575b5f5ffd5b6100566100ea565b6040516100639190610b8a565b60405180910390f35b610074610183565b6040516100819190610d81565b60405180910390f35b6100a4600480360381019061009f9190610dcf565b6106d7565b6040516100b19190610e66565b60405180910390f35b6100d460048036038101906100cf9190610eb0565b6109b2565b6040516100e19190610eea565b60405180910390f35b60605f6100f5610a38565b90508060030180548060200260200160405190810160405280929190818152602001828054801561017857602002820191905f5260205f20905b815f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001906001019080831161012f575b505050505091505090565b60605f61018e610a38565b90505f816001018054905090505f826003018054905067ffffffffffffffff8111156101bd576101bc610f03565b5b6040519080825280602002602001820160405280156101eb5781602001602082028036833780820191505090505b5090505f5b82811015610376575f84600101828154811061020f5761020e610f30565b5b905f5260205f2090600891828204019190066004029054906101000a900460e01b90505f855f015f837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020015f205f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f5b8660030180549050811015610366578173ffffffffffffffffffffffffffffffffffffffff168760030182815481106102e5576102e4610f30565b5b905f5260205f20015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16036103595784818151811061033b5761033a610f30565b5b60200260200101805180919061035090610f93565b81525050610366565b80806001019150506102a9565b50505080806001019150506101f0565b50826003018054905067ffffffffffffffff81111561039857610397610f03565b5b6040519080825280602002602001820160405280156103d157816020015b6103be610a74565b8152602001906001900390816103b65790505b5093505f5b83600301805490508110156106d0578360030181815481106103fb576103fa610f30565b5b905f5260205f20015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1685828151811061043657610435610f30565b5b60200260200101515f019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505081818151811061048657610485610f30565b5b602002602001015167ffffffffffffffff8111156104a7576104a6610f03565b5b6040519080825280602002602001820160405280156104d55781602001602082028036833780820191505090505b508582815181106104e9576104e8610f30565b5b6020026020010151602001819052505f5f90505f5b848110156106c1575f86600101828154811061051d5761051c610f30565b5b905f5260205f2090600891828204019190066004029054906101000a900460e01b90505f875f015f837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020015f205f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508760030185815481106105cb576105ca610f30565b5b905f5260205f20015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036106b2578189868151811061063957610638610f30565b5b602002602001015160200151858151811061065757610656610f30565b5b60200260200101907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152505083806106ae90610f93565b9450505b505080806001019150506104fe565b505080806001019150506103d6565b5050505090565b60605f6106e2610a38565b90505f816001018054905090505f5f90505f5b828110156107f357835f015f85600101838154811061071757610716610f30565b5b905f5260205f2090600891828204019190066004029054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020015f205f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16036107e65781806107e290610f93565b9250505b80806001019150506106f5565b508067ffffffffffffffff81111561080e5761080d610f03565b5b60405190808252806020026020018201604052801561083c5781602001602082028036833780820191505090505b5093505f5f90505f5b838110156109a8575f85600101828154811061086457610863610f30565b5b905f5260205f2090600891828204019190066004029054906101000a900460e01b9050855f015f827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020015f205f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff160361099a578087848151811061093f5761093e610f30565b5b60200260200101907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681525050828061099690610f93565b9350505b508080600101915050610845565b5050505050919050565b5f5f6109bc610a38565b9050805f015f847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020015f205f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16915050919050565b5f5f60017fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c5f1c610a699190610fda565b5f1b90508091505090565b60405180604001604052805f73ffffffffffffffffffffffffffffffffffffffff168152602001606081525090565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610af582610acc565b9050919050565b610b0581610aeb565b82525050565b5f610b168383610afc565b60208301905092915050565b5f602082019050919050565b5f610b3882610aa3565b610b428185610aad565b9350610b4d83610abd565b805f5b83811015610b7d578151610b648882610b0b565b9750610b6f83610b22565b925050600181019050610b50565b5085935050505092915050565b5f6020820190508181035f830152610ba28184610b2e565b905092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b610c3081610bfc565b82525050565b5f610c418383610c27565b60208301905092915050565b5f602082019050919050565b5f610c6382610bd3565b610c6d8185610bdd565b9350610c7883610bed565b805f5b83811015610ca8578151610c8f8882610c36565b9750610c9a83610c4d565b925050600181019050610c7b565b5085935050505092915050565b5f604083015f830151610cca5f860182610afc565b5060208301518482036020860152610ce28282610c59565b9150508091505092915050565b5f610cfa8383610cb5565b905092915050565b5f602082019050919050565b5f610d1882610baa565b610d228185610bb4565b935083602082028501610d3485610bc4565b805f5b85811015610d6f5784840389528151610d508582610cef565b9450610d5b83610d02565b925060208a01995050600181019050610d37565b50829750879550505050505092915050565b5f6020820190508181035f830152610d998184610d0e565b905092915050565b5f5ffd5b610dae81610aeb565b8114610db8575f5ffd5b50565b5f81359050610dc981610da5565b92915050565b5f60208284031215610de457610de3610da1565b5b5f610df184828501610dbb565b91505092915050565b5f82825260208201905092915050565b5f610e1482610bd3565b610e1e8185610dfa565b9350610e2983610bed565b805f5b83811015610e59578151610e408882610c36565b9750610e4b83610c4d565b925050600181019050610e2c565b5085935050505092915050565b5f6020820190508181035f830152610e7e8184610e0a565b905092915050565b610e8f81610bfc565b8114610e99575f5ffd5b50565b5f81359050610eaa81610e86565b92915050565b5f60208284031215610ec557610ec4610da1565b5b5f610ed284828501610e9c565b91505092915050565b610ee481610aeb565b82525050565b5f602082019050610efd5f830184610edb565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f819050919050565b5f610f9d82610f8a565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610fcf57610fce610f5d565b5b600182019050919050565b5f610fe482610f8a565b9150610fef83610f8a565b925082820390508181111561100757611006610f5d565b5b9291505056fea26469706673582212209bcbe652a6e339ba5970d0e190c8df9e52154ffa09e105e7e690e9cb2b3c541e64736f6c634300081c0033

Verified Source Code Full Match

Compiler: v0.8.28+commit.7893614a EVM: prague Optimization: No
DiamondLoupeFacet.sol 102 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import "../interfaces/IDiamondLoupe.sol";
import "../libraries/DiamondLib.sol";

/**
 * @title DiamondLoupeFacet
 * @notice Facet for diamond loupe functionality
 * @dev Implements EIP-2535 Diamond Standard loupe operations
 */
contract DiamondLoupeFacet is IDiamondLoupe {
    /**
     * @notice Gets all facet addresses and their four byte function selectors
     * @return facets_ Array of Facet structs
     */
    function facets() external view override returns (Facet[] memory facets_) {
        DiamondLib.DiamondStorage storage ds = DiamondLib.diamondStorage();
        uint256 selectorCount = ds.selectors.length;
        // Create an array to store facet selector counts
        uint256[] memory facetSelectorCounts = new uint256[](ds.facetAddresses.length);

        // Count selectors for each facet
        for (uint256 selectorIndex; selectorIndex < selectorCount; selectorIndex++) {
            bytes4 selector = ds.selectors[selectorIndex];
            address facet = ds.facetAddressAndSelectorPosition[selector].facetAddress;
            for (uint256 facetIndex; facetIndex < ds.facetAddresses.length; facetIndex++) {
                if (ds.facetAddresses[facetIndex] == facet) {
                    facetSelectorCounts[facetIndex]++;
                    break;
                }
            }
        }

        // Create facets array
        facets_ = new Facet[](ds.facetAddresses.length);
        for (uint256 facetIndex; facetIndex < ds.facetAddresses.length; facetIndex++) {
            facets_[facetIndex].facetAddress = ds.facetAddresses[facetIndex];
            facets_[facetIndex].functionSelectors = new bytes4[](facetSelectorCounts[facetIndex]);

            uint256 currentSelectorIndex = 0;
            for (uint256 selectorIndex; selectorIndex < selectorCount; selectorIndex++) {
                bytes4 selector = ds.selectors[selectorIndex];
                address facet = ds.facetAddressAndSelectorPosition[selector].facetAddress;
                if (facet == ds.facetAddresses[facetIndex]) {
                    facets_[facetIndex].functionSelectors[currentSelectorIndex] = selector;
                    currentSelectorIndex++;
                }
            }
        }
    }

    /**
     * @notice Gets all the function selectors supported by a specific facet
     * @param facet_ The facet address
     * @return facetFunctionSelectors_ Array of function selectors
     */
    function facetFunctionSelectors(
        address facet_
    ) external view override returns (bytes4[] memory facetFunctionSelectors_) {
        DiamondLib.DiamondStorage storage ds = DiamondLib.diamondStorage();
        uint256 selectorCount = ds.selectors.length;
        uint256 facetSelectorCount = 0;

        // Count selectors for this facet
        for (uint256 selectorIndex; selectorIndex < selectorCount; selectorIndex++) {
            if (facet_ == ds.facetAddressAndSelectorPosition[ds.selectors[selectorIndex]].facetAddress) {
                facetSelectorCount++;
            }
        }

        // Create array and populate
        facetFunctionSelectors_ = new bytes4[](facetSelectorCount);
        uint256 currentIndex = 0;
        for (uint256 selectorIndex; selectorIndex < selectorCount; selectorIndex++) {
            bytes4 selector = ds.selectors[selectorIndex];
            if (facet_ == ds.facetAddressAndSelectorPosition[selector].facetAddress) {
                facetFunctionSelectors_[currentIndex] = selector;
                currentIndex++;
            }
        }
    }

    /**
     * @notice Get all the facet addresses used by a diamond
     * @return facetAddresses_ Array of facet addresses
     */
    function facetAddresses() external view override returns (address[] memory facetAddresses_) {
        DiamondLib.DiamondStorage storage ds = DiamondLib.diamondStorage();
        facetAddresses_ = ds.facetAddresses;
    }

    /**
     * @notice Gets the facet that supports the given selector
     * @param functionSelector_ The function selector
     * @return facetAddress_ The facet address that supports the selector
     */
    function facetAddress(bytes4 functionSelector_) external view override returns (address facetAddress_) {
        DiamondLib.DiamondStorage storage ds = DiamondLib.diamondStorage();
        facetAddress_ = ds.facetAddressAndSelectorPosition[functionSelector_].facetAddress;
    }
}
IDiamondCut.sol 31 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

/**
 * @title IDiamondCut
 * @notice Interface for diamond cut functionality
 * @dev EIP-2535 Diamond Standard interface
 */
interface IDiamondCut {
    enum FacetCutAction {
        Add,
        Replace,
        Remove
    }

    struct FacetCut {
        address facetAddress;
        FacetCutAction action;
        bytes4[] functionSelectors;
    }

    /**
     * @notice Add/replace/remove any number of functions and optionally execute a function with delegatecall
     * @param diamondCut Contains the facet addresses and function selectors
     * @param init The address of the contract or facet to execute initCalldata
     * @param initCalldata A function call, including function selector and arguments executed with delegatecall on init
     */
    function diamondCut(FacetCut[] calldata diamondCut, address init, bytes calldata initCalldata) external;

    event DiamondCut(FacetCut[] diamondCut, address init, bytes initCalldata);
}
IDiamondLoupe.sol 40 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

/**
 * @title IDiamondLoupe
 * @notice Interface for diamond loupe functionality
 * @dev EIP-2535 Diamond Standard loupe interface
 */
interface IDiamondLoupe {
    struct Facet {
        address facetAddress;
        bytes4[] functionSelectors;
    }

    /**
     * @notice Gets all facet addresses and their four byte function selectors
     * @return facets_ Array of Facet structs
     */
    function facets() external view returns (Facet[] memory facets_);

    /**
     * @notice Gets all the function selectors supported by a specific facet
     * @param facet The facet address
     * @return facetFunctionSelectors_ Array of function selectors
     */
    function facetFunctionSelectors(address facet) external view returns (bytes4[] memory facetFunctionSelectors_);

    /**
     * @notice Get all the facet addresses used by a diamond
     * @return facetAddresses_ Array of facet addresses
     */
    function facetAddresses() external view returns (address[] memory facetAddresses_);

    /**
     * @notice Gets the facet that supports the given selector
     * @param functionSelector The function selector
     * @return facetAddress_ The facet address that supports the selector
     */
    function facetAddress(bytes4 functionSelector) external view returns (address facetAddress_);
}
DiamondLib.sol 184 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import "../interfaces/IDiamondCut.sol";

/**
 * @title DiamondLib
 * @notice Core library for diamond functionality
 * @dev Implements EIP-2535 Diamond Standard core logic
 */
library DiamondLib {
    bytes32 constant DIAMOND_STORAGE_POSITION = bytes32(uint256(keccak256("diamond.standard.diamond.storage")) - 1);

    struct FacetAddressAndSelectorPosition {
        address facetAddress;
        uint16 selectorPosition;
    }

    struct DiamondStorage {
        // Maps function selectors to the facet that executes the functions
        mapping(bytes4 => FacetAddressAndSelectorPosition) facetAddressAndSelectorPosition;
        bytes4[] selectors;
        mapping(address => uint256) facetAddressToSelectorCount;
        address[] facetAddresses;
        // Owner of the diamond
        address contractOwner;
    }

    function diamondStorage() internal pure returns (DiamondStorage storage ds) {
        bytes32 position = DIAMOND_STORAGE_POSITION;
        assembly {
            ds.slot := position
        }
    }

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
    event DiamondCut(IDiamondCut.FacetCut[] diamondCut, address init, bytes initCalldata);

    function setContractOwner(address newOwner) internal {
        DiamondStorage storage ds = diamondStorage();
        address previousOwner = ds.contractOwner;
        ds.contractOwner = newOwner;
        emit OwnershipTransferred(previousOwner, newOwner);
    }

    function contractOwner() internal view returns (address contractOwner_) {
        contractOwner_ = diamondStorage().contractOwner;
    }

    function enforceIsContractOwner() internal view {
        require(msg.sender == diamondStorage().contractOwner, "DiamondLib: Must be contract owner");
    }

    function diamondCut(IDiamondCut.FacetCut[] memory diamondCut_, address init, bytes memory initCalldata) internal {
        for (uint256 facetIndex; facetIndex < diamondCut_.length; facetIndex++) {
            IDiamondCut.FacetCutAction action = diamondCut_[facetIndex].action;
            if (action == IDiamondCut.FacetCutAction.Add) {
                addFunctions(diamondCut_[facetIndex].facetAddress, diamondCut_[facetIndex].functionSelectors);
            } else if (action == IDiamondCut.FacetCutAction.Replace) {
                replaceFunctions(diamondCut_[facetIndex].facetAddress, diamondCut_[facetIndex].functionSelectors);
            } else if (action == IDiamondCut.FacetCutAction.Remove) {
                removeFunctions(diamondCut_[facetIndex].facetAddress, diamondCut_[facetIndex].functionSelectors);
            } else {
                revert("DiamondCutFacet: Incorrect FacetCutAction");
            }
        }
        emit DiamondCut(diamondCut_, init, initCalldata);
        initializeDiamondCut(init, initCalldata);
    }

    function addFunctions(address facetAddress, bytes4[] memory functionSelectors) internal {
        require(functionSelectors.length > 0, "DiamondLib: No selectors in facet to cut");
        DiamondStorage storage ds = diamondStorage();
        uint16 selectorCount = uint16(ds.selectors.length);
        require(facetAddress != address(0), "DiamondLib: Add facet can't be address(0)");
        enforceHasContractCode(facetAddress, "DiamondLib: Add facet has no code");
        for (uint256 selectorIndex; selectorIndex < functionSelectors.length; selectorIndex++) {
            bytes4 selector = functionSelectors[selectorIndex];
            address oldFacetAddress = ds.facetAddressAndSelectorPosition[selector].facetAddress;
            require(oldFacetAddress == address(0), "DiamondLib: Can't add function that already exists");
            ds.facetAddressAndSelectorPosition[selector] = FacetAddressAndSelectorPosition(facetAddress, selectorCount);
            ds.selectors.push(selector);
            selectorCount++;
        }
        if (ds.facetAddressToSelectorCount[facetAddress] == 0) {
            ds.facetAddresses.push(facetAddress);
        }
        ds.facetAddressToSelectorCount[facetAddress] += functionSelectors.length;
    }

    function replaceFunctions(address facetAddress, bytes4[] memory functionSelectors) internal {
        require(functionSelectors.length > 0, "DiamondLib: No selectors in facet to cut");
        DiamondStorage storage ds = diamondStorage();
        require(facetAddress != address(0), "DiamondLib: Replace facet can't be address(0)");
        enforceHasContractCode(facetAddress, "DiamondLib: Replace facet has no code");
        for (uint256 selectorIndex; selectorIndex < functionSelectors.length; selectorIndex++) {
            bytes4 selector = functionSelectors[selectorIndex];
            address oldFacetAddress = ds.facetAddressAndSelectorPosition[selector].facetAddress;
            require(oldFacetAddress != facetAddress, "DiamondLib: Can't replace function with same function");
            require(oldFacetAddress != address(0), "DiamondLib: Can't replace function that doesn't exist");
            // Replace old facet address
            ds.facetAddressAndSelectorPosition[selector].facetAddress = facetAddress;
            if (ds.facetAddressToSelectorCount[facetAddress] == 0) {
                ds.facetAddresses.push(facetAddress);
            }
            ds.facetAddressToSelectorCount[facetAddress]++;
            ds.facetAddressToSelectorCount[oldFacetAddress]--;
            if (ds.facetAddressToSelectorCount[oldFacetAddress] == 0) {
                removeFacetAddress(ds, oldFacetAddress);
            }
        }
    }

    function removeFunctions(address facetAddress, bytes4[] memory functionSelectors) internal {
        require(functionSelectors.length > 0, "DiamondLib: No selectors in facet to cut");
        DiamondStorage storage ds = diamondStorage();
        require(facetAddress == address(0), "DiamondLib: Remove facet address must be address(0)");
        for (uint256 selectorIndex; selectorIndex < functionSelectors.length; selectorIndex++) {
            bytes4 selector = functionSelectors[selectorIndex];
            FacetAddressAndSelectorPosition memory oldFacetAddressAndSelectorPosition = ds
                .facetAddressAndSelectorPosition[selector];
            require(
                oldFacetAddressAndSelectorPosition.facetAddress != address(0),
                "DiamondLib: Can't remove function that doesn't exist"
            );
            // Replace selector with last selector
            uint256 selectorPosition = oldFacetAddressAndSelectorPosition.selectorPosition;
            uint256 lastSelectorPosition = ds.selectors.length - 1;
            // If not the same then replace selector with last selector
            if (selectorPosition != lastSelectorPosition) {
                bytes4 lastSelector = ds.selectors[lastSelectorPosition];
                ds.selectors[selectorPosition] = lastSelector;
                ds.facetAddressAndSelectorPosition[lastSelector].selectorPosition = uint16(selectorPosition);
            }
            // Delete the last selector
            ds.selectors.pop();
            delete ds.facetAddressAndSelectorPosition[selector];
            address oldFacetAddress = oldFacetAddressAndSelectorPosition.facetAddress;
            ds.facetAddressToSelectorCount[oldFacetAddress]--;
            if (ds.facetAddressToSelectorCount[oldFacetAddress] == 0) {
                removeFacetAddress(ds, oldFacetAddress);
            }
        }
    }

    function removeFacetAddress(DiamondStorage storage ds, address facetAddress) internal {
        uint256 facetAddressCount = ds.facetAddresses.length;
        for (uint256 i; i < facetAddressCount; i++) {
            if (ds.facetAddresses[i] == facetAddress) {
                ds.facetAddresses[i] = ds.facetAddresses[facetAddressCount - 1];
                ds.facetAddresses.pop();
                break;
            }
        }
    }

    function initializeDiamondCut(address init, bytes memory initCalldata) internal {
        if (init == address(0)) {
            require(initCalldata.length == 0, "DiamondLib: init is address(0) but initCalldata is not empty");
        } else {
            require(initCalldata.length > 0, "DiamondLib: initCalldata is empty but init is not address(0)");
            if (init != address(this)) {
                enforceHasContractCode(init, "DiamondLib: init address has no code");
            }
            (bool success, bytes memory error) = init.delegatecall(initCalldata);
            if (!success) {
                if (error.length > 0) {
                    // bubble up the error
                    revert(string(error));
                } else {
                    revert("DiamondLib: initializeDiamondCut failed");
                }
            }
        }
    }

    function enforceHasContractCode(address facet, string memory errorMessage) internal view {
        uint256 contractSize;
        assembly {
            contractSize := extcodesize(facet)
        }
        require(contractSize > 0, errorMessage);
    }
}

Read Contract

facetAddress 0xcdffacc6 → address
facetAddresses 0x52ef6b2c → address[]
facetFunctionSelectors 0xadfca15e → bytes4[]
facets 0x7a0ed627 → tuple[]

Recent Transactions

No transactions found for this address