ETH Price: $3,874.82 (+5.52%)

Contract

0x5B1f4a295431689C9325b72261D4D3D5eD57131B

Overview

ETH Balance

0 ETH

ETH Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

Please try again later

Parent Transaction Hash Block From To
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
ConfigFacet

Compiler Version
v0.8.20+commit.a1b79de6

Optimization Enabled:
Yes with 20000 runs

Other Settings:
default evmVersion
File 1 of 5 : ConfigFacet.sol
// SPDX-License-Identifier: GNU GPLv3
pragma solidity 0.8.20;

import {LibDiamond} from "../../libraries/LibDiamond.sol";
import {AppStorage} from "../../libraries/AppStorage.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";

contract ConfigFacet is ReentrancyGuard {
    event TokenSupported(address tokenAddress);
    event Blacklisted(address user, bool isBlacklisted);
    event TokenDepositLimit(address tokenAddress, uint256 limit);

    /// @notice Checks if a token is supported or not.
    function isTokenSupported(
        address _tokenAddress
    ) external view returns (bool) {
        return AppStorage.configStorage().supportedTokens[_tokenAddress];
    }

    /// @notice Returns the total number of supported tokens.
    function getTotalToken() external view returns (uint256) {
        return AppStorage.configStorage().totalTokens;
    }

    /// @notice Returns facet name.
    function getConfigFacetName() external pure returns (bytes4) {
        return bytes4(keccak256(bytes("ConfigFacet")));
    }

    /// @notice Adds support for a token.
    /// @dev Only the contract owner can call this function.
    /// @param _tokenAddress The address of the token to be supported.
    function supportToken(address _tokenAddress) external nonReentrant {
        AppStorage.enforceNotExodusMode();
        AppStorage.enforceIsNumeOwner();
        AppStorage.ConfigStorage storage cs = AppStorage.configStorage();

        if (_tokenAddress == address(0) || _tokenAddress == address(this)) {
            revert AppStorage.InvalidAddress();
        }
        require(
            cs.supportedTokens[_tokenAddress] == false,
            "ConfigFacet: Token already supported"
        );

        ++cs.totalTokens;
        cs.supportedTokens[_tokenAddress] = true;

        emit TokenSupported(_tokenAddress);
    }

    function setBlacklistStatus(
        address _user,
        bool _isBlacklisted
    ) external nonReentrant {
        AppStorage.enforceIsNumeOwner();
        AppStorage.userStorage().isAddressBlacklisted[_user] = _isBlacklisted;
        emit Blacklisted(_user, _isBlacklisted);
    }

    function getBlacklistStatus(address _user) external view returns (bool) {
        return AppStorage.userStorage().isAddressBlacklisted[_user];
    }

    function setTokenDepositLimit(
        address _tokenAddress,
        uint256 _limit
    ) external nonReentrant {
        AppStorage.enforceIsNumeOwner();
        AppStorage.configStorage().tokenDepositLimit[_tokenAddress] = _limit;
        emit TokenDepositLimit(_tokenAddress, _limit);
    }

    function getTokenDepositLimit(
        address _tokenAddress
    ) external view returns (uint256) {
        return AppStorage.configStorage().tokenDepositLimit[_tokenAddress];
    }

    function setSettlementTimeout(uint256 _timeout) external nonReentrant {
        AppStorage.enforceIsNumeOwner();
        require(_timeout > 10 minutes, "ConfigFacet: Invalid timeout");
        AppStorage.configStorage().SETTLEMENT_TIMEOUT = _timeout;
    }

    function getSettlementTimeout() external view returns (uint256) {
        return AppStorage.configStorage().SETTLEMENT_TIMEOUT;
    }
}

File 2 of 5 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol)

pragma solidity ^0.8.20;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant NOT_ENTERED = 1;
    uint256 private constant ENTERED = 2;

    uint256 private _status;

    /**
     * @dev Unauthorized reentrant call.
     */
    error ReentrancyGuardReentrantCall();

    constructor() {
        _status = NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be NOT_ENTERED
        if (_status == ENTERED) {
            revert ReentrancyGuardReentrantCall();
        }

        // Any calls to nonReentrant after this point will fail
        _status = ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = NOT_ENTERED;
    }

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _status == ENTERED;
    }
}

File 3 of 5 : IDiamondCut.sol
// SPDX-License-Identifier: GNU GPLv3
pragma solidity 0.8.20;

/******************************************************************************\
* https://github.com/mudgen/diamond-2-hardhat/blob/main/contracts/interfaces/IDiamondCut.sol
* Author: Nick Mudge <[email protected]> (https://twitter.com/mudgen)
* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535
/******************************************************************************/

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

    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 _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;

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

File 4 of 5 : AppStorage.sol
// SPDX-License-Identifier: GNU GPLv3
pragma solidity 0.8.20;

library AppStorage {
    bytes32 constant CONFIG_STORAGE_POSITION =
        keccak256("nume.protocol.config.storage");

    bytes32 constant USER_STORAGE_POSITION =
        keccak256("nume.protocol.user.storage");

    bytes32 constant QUEUE_STORAGE_POSITION =
        keccak256("nume.protocol.queue.storage");

    bytes32 constant NUME_STORAGE_POSITION =
        keccak256("nume.protocol.request.storage");

    struct ConfigStorage {
        bool isInExodusMode;
        uint256 totalTokens;
        uint256 numeBlockNumber;
        address verificationAddress;
        address numeOwner;
        address governorContract;
        uint256 depositsLimit;
        uint256 nftDepositsLimit;
        uint256 currDepositsQueueIndex;
        uint256 currNFTDepositsQueueIndex;
        uint256 currWithdrawalsQueueIndex;
        uint256 currNFTWithdrawalsQueueIndex;
        uint256 currCancelSubsciptionsQueueIndex;
        uint256 lastFinalizedDepositsQueueIndex;
        uint256 lastFinalizedNFTDepositsQueueIndex;
        uint256 lastFinalizedWithdrawalsQueueIndex;
        uint256 lastFinalizedNFTWithdrawalsQueueIndex;
        uint256 lastFinalizedCancelSubsciptionsQueueIndex;
        uint256 WITHDRAWAL_STAKE;
        uint256 WITHDRAWAL_REQUEST_TIMEOUT;
        uint256 SETTLEMENT_TIMEOUT;
        uint256 LAST_SETTLEMENT_TIMESTAMP;
        bytes32 settlementsRoot;
        bytes32 nftCollectionsRoot;
        mapping(address => bool) supportedTokens;
        mapping(address => uint256) tokenDepositLimit;
        bytes32[] SettlementsRootQueue;
        bytes32[] NftCollectionsRootQueue;
    }

    struct UserStorage {
        mapping(uint256 => address) depositSenderAddress;
        mapping(uint256 => address) nftDepositSenderAddress;
        mapping(uint256 => address) contractWithdrawalSenderAddress;
        mapping(uint256 => address) contractNftWithdrawalSenderAddress;
        mapping(address => uint256) userDepositCount; // userAddress => depositCount
        mapping(address => uint256) userDepositTimestamp; // userAddress => depositTimestamp
        mapping(address => uint256) userNftDepositCount; // userAddress => nft depositCount
        mapping(address => uint256) userNftDepositTimestamp; // userAddress => nft depositTimestamp
        mapping(address => mapping(address => bool)) userExodusWithdrawals; // userAddress => tokenAddress => isWithdrawn
        mapping(address => mapping(bytes32 => bool)) userExodusNFTWithdrawals; // userAddress => keccak256(NFTContractAddress, tokenID) => isWithdrawn
        mapping(address => bool) isAddressBlacklisted; // userAddress => isBlacklisted
        mapping(address => mapping(address => uint256)) userWithdrawalBalance; // userAddress => tokenAddress => withdrawal amount
        mapping(address => bytes[]) userBackendNftWithdrawalRequests; // userAddress => nftWithdrawalRequestHashes
    }

    struct QueueStorage {
        bytes32[] depositsQueue;
        bytes32[] NFTDepositsQueue;
        bytes32[] withdrawalsQueue;
        bytes32[] NFTWithdrawalsQueue;
        bytes32[] cancelSubsciptionsQueue;
    }

    struct NumeStorage {
        mapping(address => mapping(address => bool)) withdrawalRequests; // user adddress => tokenID => isWithdrawalRequested
        mapping(address => mapping(bytes32 => bool)) NFTWithdrawalRequests; // user adddress => keccak256(NFTContractAddress, tokenID) => isWithdrawalRequested
        mapping(uint256 => uint256) withdrawalRequestTimestamps; // withdrawalQueueIndex => timestamp
        mapping(uint256 => uint256) NFTWithdrawalRequestTimestamps; // nft withdrawalQueueIndex => timestamp
        mapping(address => bool) cancelSubscriptionRequests; // userAddress => isCancelRequested
        mapping(uint256 => uint256) cancelSubscriptionRequestTimestamps; // cancel subscription queue index => timestamp
    }

    function configStorage() internal pure returns (ConfigStorage storage cs) {
        bytes32 position = CONFIG_STORAGE_POSITION;
        assembly {
            cs.slot := position
        }
    }

    function queueStorage() internal pure returns (QueueStorage storage qs) {
        bytes32 position = QUEUE_STORAGE_POSITION;
        assembly {
            qs.slot := position
        }
    }

    function userStorage() internal pure returns (UserStorage storage us) {
        bytes32 position = USER_STORAGE_POSITION;
        assembly {
            us.slot := position
        }
    }

    function numeStorage() internal pure returns (NumeStorage storage ns) {
        bytes32 position = NUME_STORAGE_POSITION;
        assembly {
            ns.slot := position
        }
    }

    function enforceIsNumeOwner() internal view {
        require(
            msg.sender == configStorage().numeOwner,
            "Nume: Only Nume owner can call this function"
        );
    }

    function enforceIsGovernor() internal view {
        require(
            msg.sender == configStorage().governorContract,
            "Nume: Only governor contract can call this function"
        );
    }

    function notBlacklisted(address user) internal view {
        require(
            !userStorage().isAddressBlacklisted[user],
            "Nume: User is blacklisted"
        );
    }

    function enforceNotExodusMode() internal view {
        require(
            !configStorage().isInExodusMode,
            "Nume: Protocol is in exodus mode"
        );
    }

    error FacetNotExist();
    error ExceededMaximumDailyCalls(address user);
    error InvalidTokenAddress(address tokenAddress);
    error InvalidAmount();
    error TransactionFailed();
    error NotInExodusMode();
    error AddressBlacklisted(address user);
    error InvalidAddress();
}

File 5 of 5 : LibDiamond.sol
// SPDX-License-Identifier: GNU GPLv3
pragma solidity 0.8.20;

/******************************************************************************\
* Author: Nick Mudge <[email protected]> (https://twitter.com/mudgen)
* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535
/******************************************************************************/
import {IDiamondCut} from "../interfaces/IDiamondCut.sol";

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

error InitializationFunctionReverted(
    address _initializationContractAddress,
    bytes _calldata
);

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

    struct DiamondStorage {
        // maps function selectors to the facets that execute the functions.
        // and maps the selectors to their position in the selectorSlots array.
        // func selector => address facet, selector position
        mapping(bytes4 => bytes32) facets;
        // array of slots of function selectors.
        // each slot holds 8 function selectors.
        mapping(uint256 => bytes32) selectorSlots;
        // The number of function selectors in selectorSlots
        uint16 selectorCount;
        // Used to query if a contract implements an interface.
        // Used to implement ERC-165.
        mapping(bytes4 => bool) supportedInterfaces;
        // owner of the contract
        address diamondOwner;
    }

    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 setDiamondOwner(address _newOwner) internal {
        DiamondStorage storage ds = diamondStorage();
        address previousOwner = ds.diamondOwner;
        ds.diamondOwner = _newOwner;
        emit OwnershipTransferred(previousOwner, _newOwner);
    }

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

    function enforceIsDiamondOwner() internal view {
        require(
            msg.sender == diamondStorage().diamondOwner,
            "LibDiamond: Must be diamond owner"
        );
    }

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

    bytes32 constant CLEAR_ADDRESS_MASK =
        bytes32(uint256(0xffffffffffffffffffffffff));
    bytes32 constant CLEAR_SELECTOR_MASK = bytes32(uint256(0xffffffff << 224));

    // Internal function version of diamondCut
    // This code is almost the same as the external diamondCut,
    // except it is using 'Facet[] memory _diamondCut' instead of
    // 'Facet[] calldata _diamondCut'.
    // The code is duplicated to prevent copying calldata to memory which
    // causes an error for a two dimensional array.
    function diamondCut(
        IDiamondCut.FacetCut[] memory _diamondCut,
        address _init,
        bytes memory _calldata
    ) internal {
        DiamondStorage storage ds = diamondStorage();
        uint256 originalSelectorCount = ds.selectorCount;
        uint256 selectorCount = originalSelectorCount;
        bytes32 selectorSlot;
        // Check if last selector slot is not full
        // "selectorCount & 7" is a gas efficient modulo by eight "selectorCount % 8"
        if (selectorCount & 7 > 0) {
            // get last selectorSlot
            // "selectorSlot >> 3" is a gas efficient division by 8 "selectorSlot / 8"
            selectorSlot = ds.selectorSlots[selectorCount >> 3];
        }
        // loop through diamond cut
        for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {
            (selectorCount, selectorSlot) = addReplaceRemoveFacetSelectors(
                selectorCount,
                selectorSlot,
                _diamondCut[facetIndex].facetAddress,
                _diamondCut[facetIndex].action,
                _diamondCut[facetIndex].functionSelectors
            );

            unchecked {
                facetIndex++;
            }
        }
        if (selectorCount != originalSelectorCount) {
            ds.selectorCount = uint16(selectorCount);
        }
        // If last selector slot is not full
        // "selectorCount & 7" is a gas efficient modulo by eight "selectorCount % 8"
        if (selectorCount & 7 > 0) {
            // "selectorSlot >> 3" is a gas efficient division by 8 "selectorSlot / 8"
            ds.selectorSlots[selectorCount >> 3] = selectorSlot;
        }
        emit DiamondCut(_diamondCut, _init, _calldata);
        initializeDiamondCut(_init, _calldata);
    }

    function addReplaceRemoveFacetSelectors(
        uint256 _selectorCount,
        bytes32 _selectorSlot,
        address _newFacetAddress,
        IDiamondCut.FacetCutAction _action,
        bytes4[] memory _selectors
    ) internal returns (uint256, bytes32) {
        DiamondStorage storage ds = diamondStorage();
        require(
            _selectors.length > 0,
            "LibDiamondCut: No selectors in facet to cut"
        );
        if (_action == IDiamondCut.FacetCutAction.Add) {
            enforceHasContractCode(
                _newFacetAddress,
                "LibDiamondCut: Add facet has no code"
            );
            for (uint256 selectorIndex; selectorIndex < _selectors.length; ) {
                bytes4 selector = _selectors[selectorIndex];
                bytes32 oldFacet = ds.facets[selector];
                require(
                    address(bytes20(oldFacet)) == address(0),
                    "LibDiamondCut: Can't add function that already exists"
                );
                // add facet for selector
                ds.facets[selector] =
                    bytes20(_newFacetAddress) |
                    bytes32(_selectorCount);
                // "_selectorCount & 7" is a gas efficient modulo by eight "_selectorCount % 8"
                // " << 5 is the same as multiplying by 32 ( * 32)
                uint256 selectorInSlotPosition = (_selectorCount & 7) << 5;
                // clear selector position in slot and add selector
                _selectorSlot =
                    (_selectorSlot &
                        ~(CLEAR_SELECTOR_MASK >> selectorInSlotPosition)) |
                    (bytes32(selector) >> selectorInSlotPosition);
                // if slot is full then write it to storage
                if (selectorInSlotPosition == 224) {
                    // "_selectorSlot >> 3" is a gas efficient division by 8 "_selectorSlot / 8"
                    ds.selectorSlots[_selectorCount >> 3] = _selectorSlot;
                    _selectorSlot = 0;
                }
                _selectorCount++;

                unchecked {
                    selectorIndex++;
                }
            }
        } else if (_action == IDiamondCut.FacetCutAction.Replace) {
            enforceHasContractCode(
                _newFacetAddress,
                "LibDiamondCut: Replace facet has no code"
            );
            for (uint256 selectorIndex; selectorIndex < _selectors.length; ) {
                bytes4 selector = _selectors[selectorIndex];
                bytes32 oldFacet = ds.facets[selector];
                address oldFacetAddress = address(bytes20(oldFacet));
                // only useful if immutable functions exist
                require(
                    oldFacetAddress != address(this),
                    "LibDiamondCut: Can't replace immutable function"
                );
                require(
                    oldFacetAddress != _newFacetAddress,
                    "LibDiamondCut: Can't replace function with same function"
                );
                require(
                    oldFacetAddress != address(0),
                    "LibDiamondCut: Can't replace function that doesn't exist"
                );
                // replace old facet address
                ds.facets[selector] =
                    (oldFacet & CLEAR_ADDRESS_MASK) |
                    bytes20(_newFacetAddress);

                unchecked {
                    selectorIndex++;
                }
            }
        } else if (_action == IDiamondCut.FacetCutAction.Remove) {
            require(
                _newFacetAddress == address(0),
                "LibDiamondCut: Remove facet address must be address(0)"
            );
            // "_selectorCount >> 3" is a gas efficient division by 8 "_selectorCount / 8"
            uint256 selectorSlotCount = _selectorCount >> 3;
            // "_selectorCount & 7" is a gas efficient modulo by eight "_selectorCount % 8"
            uint256 selectorInSlotIndex = _selectorCount & 7;
            for (uint256 selectorIndex; selectorIndex < _selectors.length; ) {
                if (_selectorSlot == 0) {
                    // get last selectorSlot
                    selectorSlotCount--;
                    _selectorSlot = ds.selectorSlots[selectorSlotCount];
                    selectorInSlotIndex = 7;
                } else {
                    selectorInSlotIndex--;
                }
                bytes4 lastSelector;
                uint256 oldSelectorsSlotCount;
                uint256 oldSelectorInSlotPosition;
                // adding a block here prevents stack too deep error
                {
                    bytes4 selector = _selectors[selectorIndex];
                    bytes32 oldFacet = ds.facets[selector];
                    require(
                        address(bytes20(oldFacet)) != address(0),
                        "LibDiamondCut: Can't remove function that doesn't exist"
                    );
                    // only useful if immutable functions exist
                    require(
                        address(bytes20(oldFacet)) != address(this),
                        "LibDiamondCut: Can't remove immutable function"
                    );
                    // replace selector with last selector in ds.facets
                    // gets the last selector
                    // " << 5 is the same as multiplying by 32 ( * 32)
                    lastSelector = bytes4(
                        _selectorSlot << (selectorInSlotIndex << 5)
                    );
                    if (lastSelector != selector) {
                        // update last selector slot position info
                        ds.facets[lastSelector] =
                            (oldFacet & CLEAR_ADDRESS_MASK) |
                            bytes20(ds.facets[lastSelector]);
                    }
                    delete ds.facets[selector];
                    uint256 oldSelectorCount = uint16(uint256(oldFacet));
                    // "oldSelectorCount >> 3" is a gas efficient division by 8 "oldSelectorCount / 8"
                    oldSelectorsSlotCount = oldSelectorCount >> 3;
                    // "oldSelectorCount & 7" is a gas efficient modulo by eight "oldSelectorCount % 8"
                    // " << 5 is the same as multiplying by 32 ( * 32)
                    oldSelectorInSlotPosition = (oldSelectorCount & 7) << 5;
                }
                if (oldSelectorsSlotCount != selectorSlotCount) {
                    bytes32 oldSelectorSlot = ds.selectorSlots[
                        oldSelectorsSlotCount
                    ];
                    // clears the selector we are deleting and puts the last selector in its place.
                    oldSelectorSlot =
                        (oldSelectorSlot &
                            ~(CLEAR_SELECTOR_MASK >>
                                oldSelectorInSlotPosition)) |
                        (bytes32(lastSelector) >> oldSelectorInSlotPosition);
                    // update storage with the modified slot
                    ds.selectorSlots[oldSelectorsSlotCount] = oldSelectorSlot;
                } else {
                    // clears the selector we are deleting and puts the last selector in its place.
                    _selectorSlot =
                        (_selectorSlot &
                            ~(CLEAR_SELECTOR_MASK >>
                                oldSelectorInSlotPosition)) |
                        (bytes32(lastSelector) >> oldSelectorInSlotPosition);
                }
                if (selectorInSlotIndex == 0) {
                    delete ds.selectorSlots[selectorSlotCount];
                    _selectorSlot = 0;
                }

                unchecked {
                    selectorIndex++;
                }
            }
            _selectorCount = selectorSlotCount * 8 + selectorInSlotIndex;
        } else {
            revert("LibDiamondCut: Incorrect FacetCutAction");
        }
        return (_selectorCount, _selectorSlot);
    }

    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)
        }
        require(contractSize > 0, _errorMessage);
    }
}

Settings
{
  "evmVersion": "paris",
  "viaIR": true,
  "optimizer": {
    "enabled": true,
    "runs": 20000
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[],"name":"InvalidAddress","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"bool","name":"isBlacklisted","type":"bool"}],"name":"Blacklisted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"tokenAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"limit","type":"uint256"}],"name":"TokenDepositLimit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"tokenAddress","type":"address"}],"name":"TokenSupported","type":"event"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"getBlacklistStatus","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConfigFacetName","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getSettlementTimeout","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"}],"name":"getTokenDepositLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"}],"name":"isTokenSupported","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"bool","name":"_isBlacklisted","type":"bool"}],"name":"setBlacklistStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_timeout","type":"uint256"}],"name":"setSettlementTimeout","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"uint256","name":"_limit","type":"uint256"}],"name":"setTokenDepositLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"}],"name":"supportToken","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6080806040523461001b576001600055610b0590816100218239f35b600080fdfe6080604081815260048036101561001557600080fd5b600092833560e01c90816303a6588a146108db5750806303d29d28146107c25780630e9efa25146107665780632a4f16211461044c5780633d0673d4146103f057806358d2b4a51461036a5780635e51481e1461028a57806375151b63146101f957806379f8fc4f146101695763e9ad7f371461009157600080fd5b346101655760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610165578035916100cb6109d0565b6100d3610a0b565b6102588311156101085750507f98c199a2a06c19b820e4574aca672bc64a3ad70882a41ede5eb53cf6ea310e4b556001815580f35b90602060649251917f08c379a0000000000000000000000000000000000000000000000000000000008352820152601c60248201527f436f6e66696746616365743a20496e76616c69642074696d656f7574000000006044820152fd5b8280fd5b5050346101f55760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f5576020906101ed6101a86109a8565b73ffffffffffffffffffffffffffffffffffffffff166000527f98c199a2a06c19b820e4574aca672bc64a3ad70882a41ede5eb53cf6ea310e50602052604060002090565b549051908152f35b5080fd5b5050346101f55760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f55760209060ff61027f61023a6109a8565b73ffffffffffffffffffffffffffffffffffffffff166000527f98c199a2a06c19b820e4574aca672bc64a3ad70882a41ede5eb53cf6ea310e4f602052604060002090565b541690519015158152f35b5050346101f557807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f5577f6381540f2e0b985538bf37738a684609194c4a9f7482645a324ff7f213e7979b906102e46109a8565b6024356102ef6109d0565b6102f7610a0b565b806103418373ffffffffffffffffffffffffffffffffffffffff166000527f98c199a2a06c19b820e4574aca672bc64a3ad70882a41ede5eb53cf6ea310e50602052604060002090565b5573ffffffffffffffffffffffffffffffffffffffff8351921682526020820152a16001815580f35b5050346101f55760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f55760209060ff61027f6103ab6109a8565b73ffffffffffffffffffffffffffffffffffffffff166000527f0be433957ea43577ff4a0180f5a1ad92090f4287ac40af9aef297869d75cb676602052604060002090565b5050346101f557817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f5576020907f98c199a2a06c19b820e4574aca672bc64a3ad70882a41ede5eb53cf6ea310e38549051908152f35b509190346101f55760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f5576104866109a8565b9061048f6109d0565b60ff7f98c199a2a06c19b820e4574aca672bc64a3ad70882a41ede5eb53cf6ea310e375416610709576104c0610a0b565b73ffffffffffffffffffffffffffffffffffffffff82169182158015610700575b6106d85760ff6105308273ffffffffffffffffffffffffffffffffffffffff166000527f98c199a2a06c19b820e4574aca672bc64a3ad70882a41ede5eb53cf6ea310e4f602052604060002090565b5416610656577f98c199a2a06c19b820e4574aca672bc64a3ad70882a41ede5eb53cf6ea310e3880547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461062a577fea3145306a87baeba6bb1a8b5c8d3744f840a81cb436b3509f64fc978600cdfb94926020949260016105f59301905573ffffffffffffffffffffffffffffffffffffffff166000527f98c199a2a06c19b820e4574aca672bc64a3ad70882a41ede5eb53cf6ea310e4f602052604060002090565b60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082541617905551908152a16001815580f35b6024866011897f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b60848560208451917f08c379a00000000000000000000000000000000000000000000000000000000083528201526024808201527f436f6e66696746616365743a20546f6b656e20616c726561647920737570706f60448201527f72746564000000000000000000000000000000000000000000000000000000006064820152fd5b8482517fe6c4247b000000000000000000000000000000000000000000000000000000008152fd5b503083146104e1565b83602060649251917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602060248201527f4e756d653a2050726f746f636f6c20697320696e2065786f647573206d6f64656044820152fd5b5050346101f557817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f5576020907f98c199a2a06c19b820e4574aca672bc64a3ad70882a41ede5eb53cf6ea310e4b549051908152f35b5050346101f557807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f5576107fa6109a8565b90602435918215158093036108d7577fcf3473b85df1594d47b6958f29a32bea0abff9dd68296f7bf33443646793cfd8926108336109d0565b61083b610a0b565b6108848273ffffffffffffffffffffffffffffffffffffffff166000527f0be433957ea43577ff4a0180f5a1ad92090f4287ac40af9aef297869d75cb676602052604060002090565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0081541660ff831617905573ffffffffffffffffffffffffffffffffffffffff8351921682526020820152a16001815580f35b8380fd5b91939050346109a557807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126109a5578282019082821067ffffffffffffffff831117610979576020847f436f6e66696746616365740000000000000000000000000000000000000000008286868452600b81520152517f0e160f33000000000000000000000000000000000000000000000000000000008152f35b806041867f4e487b71000000000000000000000000000000000000000000000000000000006024945252fd5b80fd5b6004359073ffffffffffffffffffffffffffffffffffffffff821682036109cb57565b600080fd5b6002600054146109e1576002600055565b60046040517f3ee5aeb5000000000000000000000000000000000000000000000000000000008152fd5b73ffffffffffffffffffffffffffffffffffffffff7f98c199a2a06c19b820e4574aca672bc64a3ad70882a41ede5eb53cf6ea310e3b54163303610a4b57565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f4e756d653a204f6e6c79204e756d65206f776e65722063616e2063616c6c207460448201527f6869732066756e6374696f6e00000000000000000000000000000000000000006064820152fdfea2646970667358221220524702325feff38b87750a974a393332bb0ef05de56634bc348ca98a055b810564736f6c63430008140033

Deployed Bytecode

0x6080604081815260048036101561001557600080fd5b600092833560e01c90816303a6588a146108db5750806303d29d28146107c25780630e9efa25146107665780632a4f16211461044c5780633d0673d4146103f057806358d2b4a51461036a5780635e51481e1461028a57806375151b63146101f957806379f8fc4f146101695763e9ad7f371461009157600080fd5b346101655760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610165578035916100cb6109d0565b6100d3610a0b565b6102588311156101085750507f98c199a2a06c19b820e4574aca672bc64a3ad70882a41ede5eb53cf6ea310e4b556001815580f35b90602060649251917f08c379a0000000000000000000000000000000000000000000000000000000008352820152601c60248201527f436f6e66696746616365743a20496e76616c69642074696d656f7574000000006044820152fd5b8280fd5b5050346101f55760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f5576020906101ed6101a86109a8565b73ffffffffffffffffffffffffffffffffffffffff166000527f98c199a2a06c19b820e4574aca672bc64a3ad70882a41ede5eb53cf6ea310e50602052604060002090565b549051908152f35b5080fd5b5050346101f55760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f55760209060ff61027f61023a6109a8565b73ffffffffffffffffffffffffffffffffffffffff166000527f98c199a2a06c19b820e4574aca672bc64a3ad70882a41ede5eb53cf6ea310e4f602052604060002090565b541690519015158152f35b5050346101f557807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f5577f6381540f2e0b985538bf37738a684609194c4a9f7482645a324ff7f213e7979b906102e46109a8565b6024356102ef6109d0565b6102f7610a0b565b806103418373ffffffffffffffffffffffffffffffffffffffff166000527f98c199a2a06c19b820e4574aca672bc64a3ad70882a41ede5eb53cf6ea310e50602052604060002090565b5573ffffffffffffffffffffffffffffffffffffffff8351921682526020820152a16001815580f35b5050346101f55760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f55760209060ff61027f6103ab6109a8565b73ffffffffffffffffffffffffffffffffffffffff166000527f0be433957ea43577ff4a0180f5a1ad92090f4287ac40af9aef297869d75cb676602052604060002090565b5050346101f557817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f5576020907f98c199a2a06c19b820e4574aca672bc64a3ad70882a41ede5eb53cf6ea310e38549051908152f35b509190346101f55760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f5576104866109a8565b9061048f6109d0565b60ff7f98c199a2a06c19b820e4574aca672bc64a3ad70882a41ede5eb53cf6ea310e375416610709576104c0610a0b565b73ffffffffffffffffffffffffffffffffffffffff82169182158015610700575b6106d85760ff6105308273ffffffffffffffffffffffffffffffffffffffff166000527f98c199a2a06c19b820e4574aca672bc64a3ad70882a41ede5eb53cf6ea310e4f602052604060002090565b5416610656577f98c199a2a06c19b820e4574aca672bc64a3ad70882a41ede5eb53cf6ea310e3880547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461062a577fea3145306a87baeba6bb1a8b5c8d3744f840a81cb436b3509f64fc978600cdfb94926020949260016105f59301905573ffffffffffffffffffffffffffffffffffffffff166000527f98c199a2a06c19b820e4574aca672bc64a3ad70882a41ede5eb53cf6ea310e4f602052604060002090565b60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082541617905551908152a16001815580f35b6024866011897f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b60848560208451917f08c379a00000000000000000000000000000000000000000000000000000000083528201526024808201527f436f6e66696746616365743a20546f6b656e20616c726561647920737570706f60448201527f72746564000000000000000000000000000000000000000000000000000000006064820152fd5b8482517fe6c4247b000000000000000000000000000000000000000000000000000000008152fd5b503083146104e1565b83602060649251917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602060248201527f4e756d653a2050726f746f636f6c20697320696e2065786f647573206d6f64656044820152fd5b5050346101f557817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f5576020907f98c199a2a06c19b820e4574aca672bc64a3ad70882a41ede5eb53cf6ea310e4b549051908152f35b5050346101f557807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f5576107fa6109a8565b90602435918215158093036108d7577fcf3473b85df1594d47b6958f29a32bea0abff9dd68296f7bf33443646793cfd8926108336109d0565b61083b610a0b565b6108848273ffffffffffffffffffffffffffffffffffffffff166000527f0be433957ea43577ff4a0180f5a1ad92090f4287ac40af9aef297869d75cb676602052604060002090565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0081541660ff831617905573ffffffffffffffffffffffffffffffffffffffff8351921682526020820152a16001815580f35b8380fd5b91939050346109a557807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126109a5578282019082821067ffffffffffffffff831117610979576020847f436f6e66696746616365740000000000000000000000000000000000000000008286868452600b81520152517f0e160f33000000000000000000000000000000000000000000000000000000008152f35b806041867f4e487b71000000000000000000000000000000000000000000000000000000006024945252fd5b80fd5b6004359073ffffffffffffffffffffffffffffffffffffffff821682036109cb57565b600080fd5b6002600054146109e1576002600055565b60046040517f3ee5aeb5000000000000000000000000000000000000000000000000000000008152fd5b73ffffffffffffffffffffffffffffffffffffffff7f98c199a2a06c19b820e4574aca672bc64a3ad70882a41ede5eb53cf6ea310e3b54163303610a4b57565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f4e756d653a204f6e6c79204e756d65206f776e65722063616e2063616c6c207460448201527f6869732066756e6374696f6e00000000000000000000000000000000000000006064820152fdfea2646970667358221220524702325feff38b87750a974a393332bb0ef05de56634bc348ca98a055b810564736f6c63430008140033

Block Transaction Gas Used Reward
view all blocks sequenced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.