Cryo Explorer Ethereum Mainnet

Address Contract Verified

Address 0xfa86aa141e45da5183B42792d99Dede3D26Ec515
Balance 0 ETH
Nonce 1
Code Size 3307 bytes
Indexed Transactions 1 (24,428,44124,428,441)
Gas Used (indexed) 759,287
External Etherscan · Sourcify

Contract Bytecode

3307 bytes
0x60806040523661000b57005b600080356001600160e01b0319168152600080516020610c22833981519152602081905260409091205481906001600160a01b031680610075576000356001600160e01b031916604051630a82dd7360e31b815260040161006c9190610972565b60405180910390fd5b3660008037600080366000845af43d6000803e808015610094573d6000f35b3d6000fd5b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131f80546001600160a01b031981166001600160a01b03848116918217909355604051600080516020610c22833981519152939092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b60005b835181101561028557600084828151811061013c5761013c610987565b6020026020010151604001519050600085838151811061015e5761015e610987565b602002602001015160000151905081516000141561019a5760405163e767f91f60e01b81526001600160a01b038216600482015260240161006c565b60008684815181106101ae576101ae610987565b6020026020010151602001519050600060028111156101cf576101cf61099d565b8160028111156101e1576101e161099d565b14156101f6576101f182846102d0565b61026f565b600181600281111561020a5761020a61099d565b141561021a576101f1828461048b565b600281600281111561022e5761022e61099d565b141561023e576101f18284610602565b8060028111156102505761025061099d565b604051633ff4d20f60e11b815260ff909116600482015260240161006c565b505050808061027d906109c9565b91505061011f565b507f8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb6738383836040516102b993929190610a3c565b60405180910390a16102cb8282610888565b505050565b6001600160a01b0382166102f957806040516302b8da0760e21b815260040161006c9190610b3c565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131d5460408051606081019091526024808252600080516020610c22833981519152929161035091869190610c42602083013961094e565b60005b835181101561048457600084828151811061037057610370610987565b6020908102919091018101516001600160e01b031981166000908152918690526040909120549091506001600160a01b031680156103c3578160405163ebbf5d0760e01b815260040161006c9190610972565b6040805180820182526001600160a01b03808a16825261ffff80881660208085019182526001600160e01b0319881660009081528b8252958620945185549251909316600160a01b026001600160b01b0319909216929093169190911717909155600180880180549182018155835291206008820401805460e085901c60046007909416939093026101000a92830263ffffffff90930219169190911790558361046c81610b8a565b9450505050808061047c906109c9565b915050610353565b5050505050565b600080516020610c228339815191526001600160a01b0383166104c3578160405163cd98a96f60e01b815260040161006c9190610b3c565b6104e583604051806060016040528060288152602001610c8e6028913961094e565b60005b82518110156105fc57600083828151811061050557610505610987565b6020908102919091018101516001600160e01b031981166000908152918590526040909120549091506001600160a01b03163081141561055a5781604051632901806d60e11b815260040161006c9190610972565b856001600160a01b0316816001600160a01b0316141561058f5781604051631ac6ce8d60e11b815260040161006c9190610972565b6001600160a01b0381166105b85781604051637479f93960e01b815260040161006c9190610972565b506001600160e01b031916600090815260208390526040902080546001600160a01b0319166001600160a01b038616179055806105f4816109c9565b9150506104e8565b50505050565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131d54600080516020610c22833981519152906001600160a01b038416156106675760405163d091bc8160e01b81526001600160a01b038516600482015260240161006c565b60005b835181101561048457600084828151811061068757610687610987565b6020908102919091018101516001600160e01b0319811660009081528683526040908190208151808301909252546001600160a01b038116808352600160a01b90910461ffff1693820193909352909250906106f85781604051637a08a22d60e01b815260040161006c9190610972565b80516001600160a01b03163014156107255781604051630df5fd6160e31b815260040161006c9190610972565b8361072f81610bac565b94505083816020015161ffff161461080d57600085600101858154811061075857610758610987565b90600052602060002090600891828204019190066004029054906101000a900460e01b90508086600101836020015161ffff168154811061079b5761079b610987565b600091825260208083206008830401805463ffffffff60079094166004026101000a938402191660e09590951c92909202939093179055838201516001600160e01b03199390931681529087905260409020805461ffff60a01b1916600160a01b61ffff909316929092029190911790555b8460010180548061082057610820610bc3565b60008281526020808220600860001990940193840401805463ffffffff600460078716026101000a0219169055919092556001600160e01b0319909316815291859052506040902080546001600160b01b031916905580610880816109c9565b91505061066a565b6001600160a01b03821661089a575050565b6108bc82604051806060016040528060288152602001610c666028913961094e565b600080836001600160a01b0316836040516108d79190610bd9565b600060405180830381855af49150503d8060008114610912576040519150601f19603f3d011682016040523d82523d6000602084013e610917565b606091505b5091509150816105fc578051156109315780518082602001fd5b838360405163192105d760e01b815260040161006c929190610bf5565b813b806102cb57828260405163919834b960e01b815260040161006c929190610bf5565b6001600160e01b031991909116815260200190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006000198214156109dd576109dd6109b3565b5060010190565b60005b838110156109ff5781810151838201526020016109e7565b838111156105fc5750506000910152565b60008151808452610a288160208601602086016109e4565b601f01601f19169290920160200192915050565b60006060808301818452808751808352608092508286019150828160051b8701016020808b0160005b84811015610b0c57898403607f19018652815180516001600160a01b03168552838101518986019060038110610aab57634e487b7160e01b600052602160045260246000fd5b868601526040918201519186018a905281519081905290840190600090898701905b80831015610af75783516001600160e01b0319168252928601926001929092019190860190610acd565b50978501979550505090820190600101610a65565b50506001600160a01b038a16908801528681036040880152610b2e8189610a10565b9a9950505050505050505050565b6020808252825182820181905260009190848201906040850190845b81811015610b7e5783516001600160e01b03191683529284019291840191600101610b58565b50909695505050505050565b600061ffff80831681811415610ba257610ba26109b3565b6001019392505050565b600081610bbb57610bbb6109b3565b506000190190565b634e487b7160e01b600052603160045260246000fd5b60008251610beb8184602087016109e4565b9190910192915050565b6001600160a01b0383168152604060208201819052600090610c1990830184610a10565b94935050505056fec8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c4c69624469616d6f6e644375743a2041646420666163657420686173206e6f20636f64654c69624469616d6f6e644375743a205f696e6974206164647265737320686173206e6f20636f64654c69624469616d6f6e644375743a205265706c61636520666163657420686173206e6f20636f6465a264697066735822122073e1ec3b192868777b4730f9a2ebe99976a57173d8d74976d7e2b8105522d82164736f6c634300080c0033

Verified Source Code Full Match

Compiler: v0.8.12+commit.f00d7308 EVM: london Optimization: Yes (200 runs)
IERC165.sol 12 lines
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0;

interface IERC165 {
  /// @notice Query if a contract implements an interface
  /// @param interfaceId The interface identifier, as specified in ERC-165
  /// @dev Interface identification is specified in ERC-165. This function
  ///  uses less than 30,000 gas.
  /// @return `true` if the contract implements `interfaceID` and
  ///  `interfaceID` is not 0xffffffff, `false` otherwise
  function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
IDiamondCut.sol 23 lines
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0;

/******************************************************************************\
* Author: Nick Mudge <[email protected]>, Twitter/Github: @mudgen
* EIP-2535 Diamonds
/******************************************************************************/

import { IDiamond } from "./IDiamond.sol";

interface IDiamondCut is IDiamond {
  /// @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 _calldata
  /// @param _calldata A function call, including function selector and arguments
  ///                  _calldata is executed with delegatecall on _init
  function diamondCut(
    FacetCut[] calldata _diamondCut,
    address _init,
    bytes calldata _calldata
  ) external;
}
IDiamond.sol 24 lines
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0;

/******************************************************************************\
* Author: Nick Mudge <[email protected]>, Twitter/Github: @mudgen
* EIP-2535 Diamonds
/******************************************************************************/

interface IDiamond {
  enum FacetCutAction {
    Add,
    Replace,
    Remove
  }
  // Add=0, Replace=1, Remove=2

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

  event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);
}
Diamond.sol 75 lines
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0;

/******************************************************************************\
* Author: Nick Mudge <[email protected]>, Twitter/Github: @mudgen
* EIP-2535 Diamonds
*
* Implementation of a diamond.
/******************************************************************************/

import { LibDiamond } from "./libraries/LibDiamond.sol";
import { IDiamondCut } from "./interfaces/IDiamondCut.sol";
import { IDiamondLoupe } from "./interfaces/IDiamondLoupe.sol";
import { IERC173 } from "./interfaces/IERC173.sol";
import { IERC165 } from "./interfaces/IERC165.sol";

// solhint-disable no-complex-fallback
// solhint-disable no-inline-assembly
// solhint-disable no-empty-blocks

// When no function exists for function called
error FunctionNotFound(bytes4 _functionSelector);

// This is used in diamond constructor
// more arguments are added to this struct
// this avoids stack too deep errors
struct DiamondArgs {
  address owner;
  address init;
  bytes initCalldata;
}

contract Diamond {
  constructor(IDiamondCut.FacetCut[] memory _diamondCut, DiamondArgs memory _args) payable {
    LibDiamond.setContractOwner(_args.owner);
    LibDiamond.diamondCut(_diamondCut, _args.init, _args.initCalldata);

    // Code can be added here to perform actions and set state variables.
  }

  // Find facet for function that is called and execute the
  // function if a facet is found and return any value.
  fallback() external payable {
    LibDiamond.DiamondStorage storage ds;
    bytes32 position = LibDiamond.DIAMOND_STORAGE_POSITION;
    // get diamond storage
    assembly {
      ds.slot := position
    }
    // get facet from function selector
    address facet = ds.facetAddressAndSelectorPosition[msg.sig].facetAddress;
    if (facet == address(0)) {
      revert FunctionNotFound(msg.sig);
    }
    // Execute external function from facet using delegatecall and return any value.
    assembly {
      // copy function selector and any arguments
      calldatacopy(0, 0, calldatasize())
      // execute function call using the facet
      let result := delegatecall(gas(), facet, 0, calldatasize(), 0, 0)
      // get any return value
      returndatacopy(0, 0, returndatasize())
      // return any return value or error back to the caller
      switch result
      case 0 {
        revert(0, returndatasize())
      }
      default {
        return(0, returndatasize())
      }
    }
  }

  receive() external payable {}
}
LibDiamond.sol 210 lines
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0;

/******************************************************************************\
* Author: Nick Mudge <[email protected]>, Twitter/Github: @mudgen
* EIP-2535 Diamonds
/******************************************************************************/
import { IDiamond } from "../interfaces/IDiamond.sol";
import { IDiamondCut } from "../interfaces/IDiamondCut.sol";

// solhint-disable avoid-low-level-calls
// solhint-disable no-inline-assembly

// Remember to add the loupe functions from DiamondLoupeFacet to the diamond.
// The loupe functions are required by the EIP2535 Diamonds standard

error NoSelectorsGivenToAdd();
error NotContractOwner(address _user, address _contractOwner);
error NoSelectorsProvidedForFacetForCut(address _facetAddress);
error CannotAddSelectorsToZeroAddress(bytes4[] _selectors);
error NoBytecodeAtAddress(address _contractAddress, string _message);
error IncorrectFacetCutAction(uint8 _action);
error CannotAddFunctionToDiamondThatAlreadyExists(bytes4 _selector);
error CannotReplaceFunctionsFromFacetWithZeroAddress(bytes4[] _selectors);
error CannotReplaceImmutableFunction(bytes4 _selector);
error CannotReplaceFunctionWithTheSameFunctionFromTheSameFacet(bytes4 _selector);
error CannotReplaceFunctionThatDoesNotExists(bytes4 _selector);
error RemoveFacetAddressMustBeZeroAddress(address _facetAddress);
error CannotRemoveFunctionThatDoesNotExist(bytes4 _selector);
error CannotRemoveImmutableFunction(bytes4 _selector);
error InitializationFunctionReverted(address _initializationContractAddress, bytes _calldata);

library LibDiamond {
  bytes32 internal constant DIAMOND_STORAGE_POSITION = keccak256("diamond.standard.diamond.storage");

  struct FacetAddressAndSelectorPosition {
    address facetAddress;
    uint16 selectorPosition;
  }

  struct DiamondStorage {
    // function selector => facet address and selector position in selectors array
    mapping(bytes4 => FacetAddressAndSelectorPosition) facetAddressAndSelectorPosition;
    bytes4[] selectors;
    mapping(bytes4 => bool) supportedInterfaces;
    // owner of the contract
    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);

  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 {
    if (msg.sender != diamondStorage().contractOwner) {
      revert NotContractOwner(msg.sender, diamondStorage().contractOwner);
    }
  }

  event DiamondCut(IDiamondCut.FacetCut[] _diamondCut, address _init, bytes _calldata);

  // Internal function version of diamondCut
  function diamondCut(
    IDiamondCut.FacetCut[] memory _diamondCut,
    address _init,
    bytes memory _calldata
  ) internal {
    for (uint256 facetIndex; facetIndex < _diamondCut.length; facetIndex++) {
      bytes4[] memory functionSelectors = _diamondCut[facetIndex].functionSelectors;
      address facetAddress = _diamondCut[facetIndex].facetAddress;
      if (functionSelectors.length == 0) {
        revert NoSelectorsProvidedForFacetForCut(facetAddress);
      }
      IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;
      if (action == IDiamond.FacetCutAction.Add) {
        addFunctions(facetAddress, functionSelectors);
      } else if (action == IDiamond.FacetCutAction.Replace) {
        replaceFunctions(facetAddress, functionSelectors);
      } else if (action == IDiamond.FacetCutAction.Remove) {
        removeFunctions(facetAddress, functionSelectors);
      } else {
        revert IncorrectFacetCutAction(uint8(action));
      }
    }
    emit DiamondCut(_diamondCut, _init, _calldata);
    initializeDiamondCut(_init, _calldata);
  }

  function addFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {
    if (_facetAddress == address(0)) {
      revert CannotAddSelectorsToZeroAddress(_functionSelectors);
    }
    DiamondStorage storage ds = diamondStorage();
    uint16 selectorCount = uint16(ds.selectors.length);
    enforceHasContractCode(_facetAddress, "LibDiamondCut: Add facet has no code");
    for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {
      bytes4 selector = _functionSelectors[selectorIndex];
      address oldFacetAddress = ds.facetAddressAndSelectorPosition[selector].facetAddress;
      if (oldFacetAddress != address(0)) {
        revert CannotAddFunctionToDiamondThatAlreadyExists(selector);
      }
      ds.facetAddressAndSelectorPosition[selector] = FacetAddressAndSelectorPosition(_facetAddress, selectorCount);
      ds.selectors.push(selector);
      selectorCount++;
    }
  }

  function replaceFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {
    DiamondStorage storage ds = diamondStorage();
    if (_facetAddress == address(0)) {
      revert CannotReplaceFunctionsFromFacetWithZeroAddress(_functionSelectors);
    }
    enforceHasContractCode(_facetAddress, "LibDiamondCut: Replace facet has no code");
    for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {
      bytes4 selector = _functionSelectors[selectorIndex];
      address oldFacetAddress = ds.facetAddressAndSelectorPosition[selector].facetAddress;
      // can't replace immutable functions -- functions defined directly in the diamond in this case
      if (oldFacetAddress == address(this)) {
        revert CannotReplaceImmutableFunction(selector);
      }
      if (oldFacetAddress == _facetAddress) {
        revert CannotReplaceFunctionWithTheSameFunctionFromTheSameFacet(selector);
      }
      if (oldFacetAddress == address(0)) {
        revert CannotReplaceFunctionThatDoesNotExists(selector);
      }
      // replace old facet address
      ds.facetAddressAndSelectorPosition[selector].facetAddress = _facetAddress;
    }
  }

  function removeFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {
    DiamondStorage storage ds = diamondStorage();
    uint256 selectorCount = ds.selectors.length;
    if (_facetAddress != address(0)) {
      revert RemoveFacetAddressMustBeZeroAddress(_facetAddress);
    }
    for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {
      bytes4 selector = _functionSelectors[selectorIndex];
      FacetAddressAndSelectorPosition memory oldFacetAddressAndSelectorPosition = ds.facetAddressAndSelectorPosition[
        selector
      ];
      if (oldFacetAddressAndSelectorPosition.facetAddress == address(0)) {
        revert CannotRemoveFunctionThatDoesNotExist(selector);
      }

      // can't remove immutable functions -- functions defined directly in the diamond
      if (oldFacetAddressAndSelectorPosition.facetAddress == address(this)) {
        revert CannotRemoveImmutableFunction(selector);
      }
      // replace selector with last selector
      selectorCount--;
      if (oldFacetAddressAndSelectorPosition.selectorPosition != selectorCount) {
        bytes4 lastSelector = ds.selectors[selectorCount];
        ds.selectors[oldFacetAddressAndSelectorPosition.selectorPosition] = lastSelector;
        ds.facetAddressAndSelectorPosition[lastSelector].selectorPosition = oldFacetAddressAndSelectorPosition
          .selectorPosition;
      }
      // delete last selector
      ds.selectors.pop();
      delete ds.facetAddressAndSelectorPosition[selector];
    }
  }

  function initializeDiamondCut(address _init, bytes memory _calldata) internal {
    if (_init == address(0)) {
      return;
    }
    enforceHasContractCode(_init, "LibDiamondCut: _init address has no code");
    (bool success, bytes memory error) = _init.delegatecall(_calldata);
    if (!success) {
      if (error.length > 0) {
        // bubble up error
        /// @solidity memory-safe-assembly
        assembly {
          let returndata_size := mload(error)
          revert(add(32, error), returndata_size)
        }
      } else {
        revert InitializationFunctionReverted(_init, _calldata);
      }
    }
  }

  function enforceHasContractCode(address _contract, string memory _errorMessage) internal view {
    uint256 contractSize;
    assembly {
      contractSize := extcodesize(_contract)
    }
    if (contractSize == 0) {
      revert NoBytecodeAtAddress(_contract, _errorMessage);
    }
  }
}
IERC173.sol 19 lines
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0;

/// @title ERC-173 Contract Ownership Standard
///  Note: the ERC-165 identifier for this interface is 0x7f5828d0
/* is ERC165 */
interface IERC173 {
  /// @dev This emits when ownership of a contract changes.
  event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

  /// @notice Get the address of the owner
  /// @return owner_ The address of the owner.
  function owner() external view returns (address owner_);

  /// @notice Set the address of the new owner of the contract
  /// @dev Set _newOwner to address(0) to renounce any ownership.
  /// @param _newOwner The address of the new owner of the contract
  function transferOwnership(address _newOwner) external;
}
IDiamondLoupe.sol 38 lines
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0;

/******************************************************************************\
* Author: Nick Mudge <[email protected]>, Twitter/Github: @mudgen
* EIP-2535 Diamonds
/******************************************************************************/

// A loupe is a small magnifying glass used to look at diamonds.
// These functions look at diamonds
interface IDiamondLoupe {
  /// These functions are expected to be called frequently
  /// by tools.

  struct Facet {
    address facetAddress;
    bytes4[] functionSelectors;
  }

  /// @notice Gets all facet addresses and their four byte function selectors.
  /// @return facets_ Facet
  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_
  function facetFunctionSelectors(address _facet) external view returns (bytes4[] memory facetFunctionSelectors_);

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

  /// @notice Gets the facet that supports the given selector.
  /// @dev If facet is not found return address(0).
  /// @param _functionSelector The function selector.
  /// @return facetAddress_ The facet address.
  function facetAddress(bytes4 _functionSelector) external view returns (address facetAddress_);
}

Top Interactions

AddressTxnsSentReceived
0xF88e4e3d...F805 1 1

Recent Transactions

CSV
|
Hash Method Block Age From/To Value Txn Fee Type
0x1b1810e3...530868 0x04117561 24,428,441 IN 0xF88e4e3d...F805 0 ETH EIP-1559