ETH Price: $2,157.41 (-1.81%)

Contract

0xd08cAB25309DFeA0A48dB8E9ef3d5aFA58cd37bB
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

1 Internal Transaction found.

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Method Block
From
To
0x60808060236825912025-10-29 10:55:11141 days ago1761735311  Contract Creation0 ETH
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
BridgeFacet

Compiler Version
v0.8.28+commit.7893614a

Optimization Enabled:
Yes with 4000 runs

Other Settings:
prague EvmVersion
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;

import {MoreVaultsLib} from "../libraries/MoreVaultsLib.sol";
import {PausableUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol";
import {IVaultFacet} from "../interfaces/facets/IVaultFacet.sol";
import {IERC4626} from "@openzeppelin/contracts/interfaces/IERC4626.sol";
import {BaseFacetInitializer} from "./BaseFacetInitializer.sol";
import {IMoreVaultsRegistry} from "../interfaces/IMoreVaultsRegistry.sol";
import {IVaultsFactory} from "../interfaces/IVaultsFactory.sol";
import {Math} from "@openzeppelin/contracts/utils/math/Math.sol";
import {AccessControlLib} from "../libraries/AccessControlLib.sol";
import {IBridgeAdapter} from "../interfaces/IBridgeAdapter.sol";
import {IOracleRegistry} from "../interfaces/IOracleRegistry.sol";
import {IBridgeFacet} from "../interfaces/facets/IBridgeFacet.sol";
import {IERC20} from "@openzeppelin/contracts/interfaces/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import {MessagingFee} from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol";

contract BridgeFacet is PausableUpgradeable, BaseFacetInitializer, IBridgeFacet, ReentrancyGuard {
    using SafeERC20 for IERC20;
    using Math for uint256;

    event AccountingInfoUpdated(bytes32 indexed guid, uint256 sumOfSpokesUsdValue, bool readSuccess);
    event OracleCrossChainAccountingUpdated(bool indexed isTrue);

    function INITIALIZABLE_STORAGE_SLOT() internal pure override returns (bytes32) {
        return keccak256("MoreVaults.storage.initializable.BridgeFacet");
    }

    function facetName() external pure returns (string memory) {
        return "BridgeFacet";
    }

    function facetVersion() external pure returns (string memory) {
        return "1.0.0";
    }

    function initialize(bytes calldata) external initializerFacet initializer {
        MoreVaultsLib.MoreVaultsStorage storage ds = MoreVaultsLib.moreVaultsStorage();
        ds.supportedInterfaces[type(IBridgeFacet).interfaceId] = true; // IBridgeFacet interface
    }

    function accountingBridgeFacet() public view returns (uint256 sum, bool isPositive) {
        MoreVaultsLib.MoreVaultsStorage storage ds = MoreVaultsLib.moreVaultsStorage();
        IVaultsFactory factory = IVaultsFactory(ds.factory);
        uint32 localEid = factory.localEid();
        (uint32[] memory eids, address[] memory vaults) = factory.hubToSpokes(localEid, address(this));
        for (uint256 i = 0; i < vaults.length;) {
            IMoreVaultsRegistry registry = IMoreVaultsRegistry(AccessControlLib.vaultRegistry());
            IOracleRegistry oracle = registry.oracle();
            sum += oracle.getSpokeValue(address(this), eids[i]);
            unchecked {
                ++i;
            }
        }
        return (sum, true);
    }

    function onFacetRemoval(bool isReplacing) external {
        MoreVaultsLib.MoreVaultsStorage storage ds = MoreVaultsLib.moreVaultsStorage();
        ds.supportedInterfaces[type(IBridgeFacet).interfaceId] = false;

        MoreVaultsLib.removeFromFacetsForAccounting(
            ds, bytes4(keccak256(abi.encodePacked("accountingBridgeFacet()"))), isReplacing
        );
    }

    function setOraclesCrossChainAccounting(bool isTrue) external {
        AccessControlLib.validateOwner(msg.sender);
        MoreVaultsLib.MoreVaultsStorage storage ds = MoreVaultsLib.moreVaultsStorage();
        IVaultsFactory factory = IVaultsFactory(ds.factory);
        (uint32[] memory eids, address[] memory vaults) = factory.hubToSpokes(factory.localEid(), address(this));

        bool currentValue = ds.oraclesCrossChainAccounting;
        if (isTrue == currentValue) {
            revert AlreadySet();
        }
        if (isTrue && !currentValue) {
            for (uint256 i = 0; i < vaults.length;) {
                IMoreVaultsRegistry registry = IMoreVaultsRegistry(AccessControlLib.vaultRegistry());
                IOracleRegistry oracle = registry.oracle();

                if (address(oracle.getSpokeOracleInfo(address(this), eids[i]).aggregator) == address(0)) {
                    revert NoOracleForSpoke(eids[i]);
                }
                unchecked {
                    ++i;
                }
            }
        }
        if (isTrue) {
            bytes32 facetSelector = bytes4(keccak256(abi.encodePacked("accountingBridgeFacet()")));
            ds.facetsForAccounting.push(facetSelector);
        } else {
            MoreVaultsLib.removeFromFacetsForAccounting(
                ds, bytes4(keccak256(abi.encodePacked("accountingBridgeFacet()"))), false
            );
        }
        ds.oraclesCrossChainAccounting = isTrue;

        emit OracleCrossChainAccountingUpdated(isTrue);
    }

    function executeBridging(address adapter, address token, uint256 amount, bytes calldata bridgeSpecificParams)
        external
        payable
        whenNotPaused
    {
        AccessControlLib.validateCurator(msg.sender);
        _pause();
        AccessControlLib.AccessControlStorage storage acs = AccessControlLib.accessControlStorage();
        if (!IMoreVaultsRegistry(acs.moreVaultsRegistry).isBridgeAllowed(adapter)) {
            revert AdapterNotAllowed(adapter);
        }
        IERC20(token).forceApprove(adapter, amount);
        IBridgeAdapter(adapter).executeBridging{value: msg.value}(bridgeSpecificParams);
    }

    function quoteAccountingFee(bytes calldata extraOptions) external view returns (uint256 nativeFee) {
        MoreVaultsLib.MoreVaultsStorage storage ds = MoreVaultsLib.moreVaultsStorage();
        IVaultsFactory factory = IVaultsFactory(ds.factory);
        (uint32[] memory eids, address[] memory vaults) = factory.hubToSpokes(factory.localEid(), address(this));
        IBridgeAdapter adapter = IBridgeAdapter(MoreVaultsLib._getCrossChainAccountingManager());
        MessagingFee memory fee = adapter.quoteReadFee(vaults, eids, extraOptions);
        return fee.nativeFee;
    }

    function initVaultActionRequest(
        MoreVaultsLib.ActionType actionType,
        bytes calldata actionCallData,
        bytes calldata extraOptions
    ) external payable whenNotPaused nonReentrant returns (bytes32 guid) {
        MoreVaultsLib.MoreVaultsStorage storage ds = MoreVaultsLib.moreVaultsStorage();
        IVaultsFactory factory = IVaultsFactory(ds.factory);
        (uint32[] memory eids, address[] memory vaults) = factory.hubToSpokes(factory.localEid(), address(this));
        if (vaults.length != 0) {
            if (ds.oraclesCrossChainAccounting) {
                revert AccountingViaOracles();
            }
            guid = _createCrossChainRequest(ds, vaults, eids, actionType, actionCallData, extraOptions);
        }
    }

    function _createCrossChainRequest(
        MoreVaultsLib.MoreVaultsStorage storage ds,
        address[] memory vaults,
        uint32[] memory eids,
        MoreVaultsLib.ActionType actionType,
        bytes calldata actionCallData,
        bytes calldata extraOptions
    ) internal returns (bytes32 guid) {
        MoreVaultsLib.CrossChainRequestInfo memory requestInfo = MoreVaultsLib.CrossChainRequestInfo({
            initiator: msg.sender,
            timestamp: uint64(block.timestamp),
            actionType: actionType,
            actionCallData: actionCallData,
            fulfilled: false,
            finalized: false,
            totalAssets: IVaultFacet(address(this)).totalAssets()
        });
        MessagingFee memory fee =
            IBridgeAdapter(MoreVaultsLib._getCrossChainAccountingManager()).quoteReadFee(vaults, eids, extraOptions);
        if (actionType == MoreVaultsLib.ActionType.MULTI_ASSETS_DEPOSIT) {
            (,,, uint256 value) = abi.decode(requestInfo.actionCallData, (address[], uint256[], address, uint256));
            if (value + fee.nativeFee > msg.value) revert NotEnoughMsgValueProvided();
        }

        guid = IBridgeAdapter(MoreVaultsLib._getCrossChainAccountingManager()).initiateCrossChainAccounting{value: msg.value}(
            vaults, eids, extraOptions, msg.sender
        ).guid;
        ds.guidToCrossChainRequestInfo[guid] = requestInfo;
    }

    function updateAccountingInfoForRequest(bytes32 guid, uint256 sumOfSpokesUsdValue, bool readSuccess) external {
        MoreVaultsLib.MoreVaultsStorage storage ds = MoreVaultsLib.moreVaultsStorage();
        if (msg.sender != MoreVaultsLib._getCrossChainAccountingManager()) {
            revert OnlyCrossChainAccountingManager();
        }
        if (readSuccess) {
            ds.guidToCrossChainRequestInfo[guid].totalAssets +=
                MoreVaultsLib.convertUsdToUnderlying(sumOfSpokesUsdValue, Math.Rounding.Floor);
        }
        ds.guidToCrossChainRequestInfo[guid].fulfilled = readSuccess;

        emit AccountingInfoUpdated(guid, sumOfSpokesUsdValue, readSuccess);
    }

    function finalizeRequest(bytes32 guid) external payable nonReentrant returns (bytes memory result) {
        MoreVaultsLib.MoreVaultsStorage storage ds = MoreVaultsLib.moreVaultsStorage();
        MoreVaultsLib.CrossChainRequestInfo memory requestInfo = ds.guidToCrossChainRequestInfo[guid];
        if (!ds.guidToCrossChainRequestInfo[guid].fulfilled) {
            revert RequestWasntFulfilled();
        }
        if (requestInfo.timestamp + 1 hours < block.timestamp) {
            revert RequestTimedOut();
        }
        if (requestInfo.finalized) {
            revert RequestAlreadyFinalized();
        }
        ds.finalizationGuid = guid;

        bool success;
        if (requestInfo.actionType == MoreVaultsLib.ActionType.DEPOSIT) {
            (uint256 assets, address receiver) = abi.decode(requestInfo.actionCallData, (uint256, address));
            (success, result) = address(this).call(abi.encodeWithSelector(IERC4626.deposit.selector, assets, receiver));
        } else if (requestInfo.actionType == MoreVaultsLib.ActionType.MULTI_ASSETS_DEPOSIT) {
            (address[] memory tokens, uint256[] memory assets, address receiver, uint256 value) =
                abi.decode(requestInfo.actionCallData, (address[], uint256[], address, uint256));
            (success, result) = address(this).call{value: value}(
                abi.encodeWithSelector(
                    bytes4(keccak256("deposit(address[],uint256[],address)")), tokens, assets, receiver
                )
            );
        } else if (requestInfo.actionType == MoreVaultsLib.ActionType.MINT) {
            (uint256 shares, address receiver) = abi.decode(requestInfo.actionCallData, (uint256, address));
            (success, result) = address(this).call(abi.encodeWithSelector(IERC4626.mint.selector, shares, receiver));
        } else if (requestInfo.actionType == MoreVaultsLib.ActionType.WITHDRAW) {
            (uint256 assets, address receiver, address owner) =
                abi.decode(requestInfo.actionCallData, (uint256, address, address));
            (success, result) =
                address(this).call(abi.encodeWithSelector(IERC4626.withdraw.selector, assets, receiver, owner));
        } else if (requestInfo.actionType == MoreVaultsLib.ActionType.REDEEM) {
            (uint256 shares, address receiver, address owner) =
                abi.decode(requestInfo.actionCallData, (uint256, address, address));
            (success, result) =
                address(this).call(abi.encodeWithSelector(IERC4626.redeem.selector, shares, receiver, owner));
        } else if (requestInfo.actionType == MoreVaultsLib.ActionType.SET_FEE) {
            uint96 fee = abi.decode(requestInfo.actionCallData, (uint96));
            (success,) = address(this).call(abi.encodeWithSelector(IVaultFacet.setFee.selector, fee));
        }
        if (!success) revert FinalizationCallFailed();

        ds.guidToCrossChainRequestInfo[guid].finalized = true;
        ds.finalizationGuid = 0;
    }

    function getRequestInfo(bytes32 guid) external view returns (MoreVaultsLib.CrossChainRequestInfo memory) {
        MoreVaultsLib.MoreVaultsStorage storage ds = MoreVaultsLib.moreVaultsStorage();
        return ds.guidToCrossChainRequestInfo[guid];
    }
}

File 2 of 41 : MoreVaultsLib.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;

import {AccessControlLib} from "./AccessControlLib.sol";
import {IDiamondCut} from "../interfaces/facets/IDiamondCut.sol";
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import {IOracleRegistry} from "../interfaces/IOracleRegistry.sol";
import {IMoreVaultsRegistry} from "../interfaces/IMoreVaultsRegistry.sol";
import {IVaultsFactory} from "../interfaces/IVaultsFactory.sol";
import {IAggregatorV2V3Interface} from "../interfaces/Chainlink/IAggregatorV2V3Interface.sol";
import {Math} from "@openzeppelin/contracts/utils/math/Math.sol";
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import {IERC20} from "@openzeppelin/contracts/interfaces/IERC20.sol";
import {
    IGenericMoreVaultFacet,
    IGenericMoreVaultFacetInitializable
} from "../interfaces/facets/IGenericMoreVaultFacetInitializable.sol";

bytes32 constant BEFORE_ACCOUNTING_SELECTOR = 0xa85367f800000000000000000000000000000000000000000000000000000000;
bytes32 constant BEFORE_ACCOUNTING_FAILED_ERROR = 0xc5361f8d00000000000000000000000000000000000000000000000000000000;
bytes32 constant ACCOUNTING_FAILED_ERROR = 0x712f778400000000000000000000000000000000000000000000000000000000;
bytes32 constant BALANCE_OF_SELECTOR = 0x70a0823100000000000000000000000000000000000000000000000000000000;
bytes32 constant TOTAL_ASSETS_SELECTOR = 0x01e1d11400000000000000000000000000000000000000000000000000000000;
bytes32 constant TOTAL_ASSETS_RUN_FAILED = 0xb5a7047700000000000000000000000000000000000000000000000000000000;

uint256 constant MAX_WITHDRAWAL_DELAY = 14 days;

library MoreVaultsLib {
    error InitializationFunctionReverted(address _initializationContractAddress, bytes _calldata);
    error UnsupportedAsset(address);
    error FacetNotAllowed(address facet);
    error SelectorNotAllowed(bytes4 selector);
    error InvalidSelectorForFacet(bytes4 selector, address facet);
    error IncorrectFacetCutAction(uint8 action);
    error ContractDoesntHaveCode(string errorMessage);
    error ZeroAddress();
    error ImmutableFunction();
    error FunctionDoesNotExist();
    error NoSelectorsInFacetToCut();
    error FunctionAlreadyExists(address oldFacetAddress, bytes4 selector);
    error OraclePriceIsOld();
    error OraclePriceIsNegative();
    error InvalidFee();
    error AssetAlreadyAvailable();
    error InvalidAddress();
    error NoOracleForAsset();
    error FacetHasBalance(uint256 amount);
    error AccountingFailed(bytes32 selector);
    error UnsupportedProtocol(address protocol);
    error AccountingGasLimitExceeded(uint256 limit, uint256 consumption);
    error RestrictedActionInsideMulticall();
    error OnFacetRemovalFailed(address facet, bytes data);
    error FacetNameFailed(address facet);

    using EnumerableSet for EnumerableSet.AddressSet;
    using EnumerableSet for EnumerableSet.Bytes32Set;
    using Math for uint256;

    // 32 bytes keccak hash of a string to use as a diamond storage location.
    bytes32 constant MORE_VAULTS_STORAGE_POSITION = keccak256("MoreVaults.diamond.storage");

    uint96 constant FEE_BASIS_POINT = 10000; // 100%

    uint96 constant MAX_FEE = 5000; // 50%

    struct ERC4626Storage {
        IERC20 _asset;
        uint8 _underlyingDecimals;
    }

    // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ERC4626")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 constant ERC4626StorageLocation = 0x0773e532dfede91f04b12a73d3d2acd361424f41f76b4fb79f090161e36b4e00;

    struct FacetAddressAndPosition {
        address facetAddress;
        uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array
    }

    struct FacetFunctionSelectors {
        bytes4[] functionSelectors;
        uint256 facetAddressPosition; // position of facetAddress in facetAddresses array
    }

    struct PendingActions {
        bytes[] actionsData;
        uint256 pendingUntil;
    }

    struct GasLimit {
        uint48 availableTokenAccountingGas;
        uint48 heldTokenAccountingGas;
        uint48 facetAccountingGas;
        uint48 stakingTokenAccountingGas;
        uint48 nestedVaultsGas;
        uint48 value;
    }

    struct WithdrawRequest {
        uint256 timelockEndsAt;
        uint256 shares;
    }

    enum TokenType {
        HeldToken,
        StakingToken
    }

    enum ActionType {
        DEPOSIT,
        MINT,
        WITHDRAW,
        REDEEM,
        MULTI_ASSETS_DEPOSIT,
        SET_FEE
    }

    struct CrossChainRequestInfo {
        address initiator;
        uint64 timestamp;
        ActionType actionType;
        bytes actionCallData;
        bool fulfilled;
        bool finalized;
        uint256 totalAssets;
    }

    struct MoreVaultsStorage {
        // maps function selector to the facet address and
        // the position of the selector in the facetFunctionSelectors.selectors array
        mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;
        // maps facet addresses to function selectors
        mapping(address => FacetFunctionSelectors) facetFunctionSelectors;
        // facet addresses
        address[] facetAddresses;
        bytes32[] facetsForAccounting;
        // Used to query if a contract implements an interface.
        // Used to implement ERC-165.
        mapping(bytes4 => bool) supportedInterfaces;
        mapping(address => bool) isAssetAvailable;
        address[] availableAssets;
        mapping(address => bool) isAssetDepositable;
        mapping(bytes32 => EnumerableSet.AddressSet) tokensHeld;
        address wrappedNative;
        address feeRecipient;
        uint96 fee;
        uint256 depositCapacity;
        uint256 lastTotalAssets;
        uint256 actionNonce;
        mapping(uint256 => PendingActions) pendingActions;
        uint256 timeLockPeriod;
        mapping(bytes32 => EnumerableSet.AddressSet) stakingAddresses;
        mapping(address => uint256) lockedTokens;
        address minter;
        bool isNativeDeposit;
        address[] beforeAccountingFacets;
        mapping(address => address) stakingTokenToGauge;
        mapping(address => address) stakingTokenToMultiRewards;
        GasLimit gasLimit;
        mapping(TokenType => EnumerableSet.Bytes32Set) vaultExternalAssets;
        uint64 witdrawTimelock;
        mapping(address => WithdrawRequest) withdrawalRequests;
        uint256 maxSlippagePercent;
        bool isMulticall;
        address factory;
        mapping(address => uint256) curvePoolLength;
        mapping(address => uint256) depositWhitelist;
        mapping(address => bool) isNecessaryToCheckLock;
        bool isWhitelistEnabled;
        address[] depositableAssets;
        bool isHub;
        bool oraclesCrossChainAccounting;
        address crossChainAccountingManager;
        mapping(bytes32 => CrossChainRequestInfo) guidToCrossChainRequestInfo;
        bytes32 finalizationGuid;
        bool isWithdrawalQueueEnabled;
        uint96 withdrawalFee;
    }

    event DiamondCut(IDiamondCut.FacetCut[] _diamondCut);
    event FeeSet(uint96 previousFee, uint96 newFee);
    event FeeRecipientSet(address indexed previousRecipient, address indexed newRecipient);
    event AssetToManageAdded(address indexed asset);
    event AssetToDepositEnabled(address indexed asset);
    event AssetToDepositDisabled(address indexed asset);
    event TimeLockPeriodSet(uint256 previousPeriod, uint256 newPeriod);
    event DepositCapacitySet(uint256 previousCapacity, uint256 newCapacity);

    function moreVaultsStorage() internal pure returns (MoreVaultsStorage storage ds) {
        bytes32 position = MORE_VAULTS_STORAGE_POSITION;
        // assigns struct storage slot to the storage position
        assembly {
            ds.slot := position
        }
    }

    function getERC4626Storage() internal pure returns (ERC4626Storage storage $) {
        assembly {
            $.slot := ERC4626StorageLocation
        }
    }

    function validateAddressWhitelisted(address protocol) internal view {
        AccessControlLib.AccessControlStorage storage acs = AccessControlLib.accessControlStorage();
        if (!IMoreVaultsRegistry(acs.moreVaultsRegistry).isWhitelisted(protocol)) revert UnsupportedProtocol(protocol);
    }

    function validateAssetAvailable(address asset) internal view {
        MoreVaultsStorage storage ds = moreVaultsStorage();
        if (asset == address(0)) asset = ds.wrappedNative;
        if (!ds.isAssetAvailable[asset]) revert UnsupportedAsset(asset);
    }

    function validateAssetDepositable(address asset) internal view {
        MoreVaultsStorage storage ds = moreVaultsStorage();
        if (asset == address(0)) asset = ds.wrappedNative;
        if (!ds.isAssetDepositable[asset]) revert UnsupportedAsset(asset);
    }

    function validateNotMulticall() internal view {
        MoreVaultsStorage storage ds = moreVaultsStorage();
        if (ds.isMulticall) {
            revert RestrictedActionInsideMulticall();
        }
    }

    function removeTokenIfnecessary(EnumerableSet.AddressSet storage tokensHeld, address token) internal {
        MoreVaultsStorage storage ds = moreVaultsStorage();
        if (IERC20(token).balanceOf(address(this)) + ds.lockedTokens[token] < 10e3) {
            tokensHeld.remove(token);
        }
    }

    function convertToUnderlying(address _token, uint256 amount, Math.Rounding rounding)
        internal
        view
        returns (uint256)
    {
        if (amount == 0) return 0;

        // Scope 1: Token validation and setup
        address resolvedToken;
        address underlyingToken;
        {
            MoreVaultsStorage storage ds = moreVaultsStorage();
            resolvedToken = _token == address(0) ? address(ds.wrappedNative) : _token;
            underlyingToken = address(getERC4626Storage()._asset);

            if (resolvedToken == underlyingToken) {
                return amount;
            }
        }

        // Scope 2: Oracle setup and input token price
        uint256 inputTokenPrice;
        uint8 inputTokenOracleDecimals;
        address oracleDenominationAsset;
        {
            IMoreVaultsRegistry registry = IMoreVaultsRegistry(AccessControlLib.vaultRegistry());
            IOracleRegistry oracle = registry.oracle();
            oracleDenominationAsset = registry.getDenominationAsset();

            IAggregatorV2V3Interface aggregator =
                IAggregatorV2V3Interface(oracle.getOracleInfo(resolvedToken).aggregator);
            inputTokenPrice = oracle.getAssetPrice(resolvedToken);
            inputTokenOracleDecimals = aggregator.decimals();
        }

        // Scope 3: Price conversion calculation
        uint256 finalPriceForConversion = inputTokenPrice;
        if (underlyingToken != oracleDenominationAsset) {
            IMoreVaultsRegistry registry = IMoreVaultsRegistry(AccessControlLib.vaultRegistry());
            IOracleRegistry oracle = registry.oracle();

            IAggregatorV2V3Interface aggregator =
                IAggregatorV2V3Interface(oracle.getOracleInfo(underlyingToken).aggregator);
            uint256 underlyingTokenPrice = oracle.getAssetPrice(underlyingToken);
            uint8 underlyingTokenOracleDecimals = aggregator.decimals();

            finalPriceForConversion =
                inputTokenPrice.mulDiv(10 ** underlyingTokenOracleDecimals, underlyingTokenPrice, rounding);
        }

        // Final conversion calculation
        return amount.mulDiv(
            finalPriceForConversion * 10 ** IERC20Metadata(underlyingToken).decimals(),
            10 ** (inputTokenOracleDecimals + IERC20Metadata(resolvedToken).decimals()),
            rounding
        );
    }

    function convertUnderlyingToUsd(uint256 amount, Math.Rounding rounding) internal view returns (uint256) {
        IOracleRegistry oracle = IMoreVaultsRegistry(AccessControlLib.vaultRegistry()).oracle();
        address underlyingToken = address(getERC4626Storage()._asset);
        return amount.mulDiv(
            oracle.getAssetPrice(underlyingToken), 10 ** IERC20Metadata(underlyingToken).decimals(), rounding
        );
    }

    function convertUsdToUnderlying(uint256 amount, Math.Rounding rounding) internal view returns (uint256) {
        IOracleRegistry oracle = IMoreVaultsRegistry(AccessControlLib.vaultRegistry()).oracle();
        address underlyingToken = address(getERC4626Storage()._asset);
        return amount.mulDiv(
            10 ** IERC20Metadata(underlyingToken).decimals(), oracle.getAssetPrice(underlyingToken), rounding
        );
    }

    function _setFeeRecipient(address recipient) internal {
        MoreVaultsStorage storage ds = moreVaultsStorage();
        if (recipient == address(0)) {
            revert ZeroAddress();
        }
        address previousRecipient = ds.feeRecipient;
        ds.feeRecipient = recipient;
        emit FeeRecipientSet(previousRecipient, recipient);
    }

    function _setFee(uint96 fee) internal {
        MoreVaultsStorage storage ds = moreVaultsStorage();
        uint96 previousFee = ds.fee;
        if (fee > MAX_FEE) {
            revert InvalidFee();
        }
        ds.fee = fee;

        emit FeeSet(previousFee, fee);
    }

    function _setDepositCapacity(uint256 capacity) internal {
        MoreVaultsStorage storage ds = moreVaultsStorage();
        uint256 previousCapacity = ds.depositCapacity;
        ds.depositCapacity = capacity;

        emit DepositCapacitySet(previousCapacity, capacity);
    }

    function _setDepositWhitelist(address[] calldata depositors, uint256[] calldata undelyingAssetCaps) internal {
        MoreVaultsStorage storage ds = moreVaultsStorage();
        for (uint256 i; i < depositors.length;) {
            ds.depositWhitelist[depositors[i]] = undelyingAssetCaps[i];
            unchecked {
                ++i;
            }
        }
    }

    function _setTimeLockPeriod(uint256 period) internal {
        MoreVaultsStorage storage ds = moreVaultsStorage();
        uint256 previousPeriod = ds.timeLockPeriod;
        ds.timeLockPeriod = period;

        emit TimeLockPeriodSet(previousPeriod, period);
    }

    function _addAvailableAsset(address asset) internal {
        if (asset == address(0)) {
            revert InvalidAddress();
        }

        MoreVaultsLib.MoreVaultsStorage storage ds = MoreVaultsLib.moreVaultsStorage();
        if (ds.isAssetAvailable[asset]) {
            revert AssetAlreadyAvailable();
        }

        AccessControlLib.AccessControlStorage storage acs = AccessControlLib.accessControlStorage();
        IMoreVaultsRegistry registry = IMoreVaultsRegistry(acs.moreVaultsRegistry);
        IOracleRegistry oracle = registry.oracle();
        if (address(oracle.getOracleInfo(asset).aggregator) == address(0)) {
            revert NoOracleForAsset();
        }

        ds.isAssetAvailable[asset] = true;
        ds.availableAssets.push(asset);

        emit AssetToManageAdded(asset);
    }

    function _enableAssetToDeposit(address asset) internal {
        if (asset == address(0)) {
            revert InvalidAddress();
        }

        MoreVaultsLib.MoreVaultsStorage storage ds = MoreVaultsLib.moreVaultsStorage();
        if (!ds.isAssetAvailable[asset]) {
            revert UnsupportedAsset(asset);
        }
        if (ds.isAssetDepositable[asset]) {
            revert AssetAlreadyAvailable();
        }
        ds.isAssetDepositable[asset] = true;
        ds.depositableAssets.push(asset);

        emit AssetToDepositEnabled(asset);
    }

    function _disableAssetToDeposit(address asset) internal {
        if (asset == address(0)) {
            revert InvalidAddress();
        }

        MoreVaultsLib.MoreVaultsStorage storage ds = MoreVaultsLib.moreVaultsStorage();
        if (!ds.isAssetDepositable[asset]) {
            revert UnsupportedAsset(asset);
        }

        ds.isAssetDepositable[asset] = false;
        for (uint256 i; i < ds.depositableAssets.length;) {
            if (ds.depositableAssets[i] == asset) {
                ds.depositableAssets[i] = ds.depositableAssets[ds.depositableAssets.length - 1];
                ds.depositableAssets.pop();
                break;
            }
            unchecked {
                ++i;
            }
        }

        emit AssetToDepositDisabled(asset);
    }

    // Internal function version of diamondCut
    function diamondCut(IDiamondCut.FacetCut[] memory _diamondCut) internal {
        AccessControlLib.AccessControlStorage storage acs = AccessControlLib.accessControlStorage();
        IMoreVaultsRegistry registry = IMoreVaultsRegistry(acs.moreVaultsRegistry);

        for (uint256 facetIndex; facetIndex < _diamondCut.length;) {
            IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;
            address facetAddress = _diamondCut[facetIndex].facetAddress;

            // Validate facet and selectors for Add and Replace actions
            if (action == IDiamondCut.FacetCutAction.Add || action == IDiamondCut.FacetCutAction.Replace) {
                // Check if facet is allowed in registry
                if (!registry.isPermissionless()) {
                    if (!registry.isFacetAllowed(facetAddress)) {
                        revert FacetNotAllowed(facetAddress);
                    }

                    for (uint256 selectorIndex; selectorIndex < _diamondCut[facetIndex].functionSelectors.length;) {
                        if (
                            registry.selectorToFacet(_diamondCut[facetIndex].functionSelectors[selectorIndex])
                                != facetAddress
                        ) {
                            revert SelectorNotAllowed(_diamondCut[facetIndex].functionSelectors[selectorIndex]);
                        }
                        unchecked {
                            ++selectorIndex;
                        }
                    }
                }
            }

            if (action == IDiamondCut.FacetCutAction.Add) {
                addFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);
                initializeAfterAddition(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].initData);
            } else if (action == IDiamondCut.FacetCutAction.Replace) {
                replaceFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);
                initializeAfterAddition(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].initData);
            } else if (action == IDiamondCut.FacetCutAction.Remove) {
                removeFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);
            } else {
                revert IncorrectFacetCutAction(uint8(action));
            }
            unchecked {
                ++facetIndex;
            }
        }
        emit DiamondCut(_diamondCut);
    }

    function addFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {
        if (_functionSelectors.length == 0) {
            revert NoSelectorsInFacetToCut();
        }
        MoreVaultsStorage storage ds = moreVaultsStorage();
        if (_facetAddress == address(0)) {
            revert ZeroAddress();
        }
        uint96 selectorPosition = uint96(ds.facetFunctionSelectors[_facetAddress].functionSelectors.length);
        // add new facet address if it does not exist
        if (selectorPosition == 0) {
            addFacet(ds, _facetAddress);
        }
        for (uint256 selectorIndex; selectorIndex < _functionSelectors.length;) {
            bytes4 selector = _functionSelectors[selectorIndex];
            address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;
            if (oldFacetAddress != address(0)) {
                revert FunctionAlreadyExists(oldFacetAddress, selector);
            }
            addFunction(ds, selector, selectorPosition, _facetAddress);
            selectorPosition++;
            unchecked {
                ++selectorIndex;
            }
        }
        // if factory is not set, then it is deployment of diamond, so link will be done on factory side
        if (factoryAddress() != address(0)) {
            IVaultsFactory(ds.factory).link(_facetAddress);
        }
    }

    function replaceFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {
        if (_functionSelectors.length == 0) {
            revert NoSelectorsInFacetToCut();
        }
        MoreVaultsStorage storage ds = moreVaultsStorage();
        if (_facetAddress == address(0)) {
            revert ZeroAddress();
        }
        uint96 selectorPosition = uint96(ds.facetFunctionSelectors[_facetAddress].functionSelectors.length);
        // add new facet address if it does not exist
        if (selectorPosition == 0) {
            addFacet(ds, _facetAddress);
        }

        address factory = ds.factory;
        for (uint256 selectorIndex; selectorIndex < _functionSelectors.length;) {
            bytes4 selector = _functionSelectors[selectorIndex];
            address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;
            if (oldFacetAddress == _facetAddress) {
                revert FunctionAlreadyExists(oldFacetAddress, selector);
            }
            removeFunction(ds, oldFacetAddress, selector, true);
            addFunction(ds, selector, selectorPosition, _facetAddress);
            selectorPosition++;
            unchecked {
                ++selectorIndex;
            }
        }
        IVaultsFactory(factory).link(_facetAddress);
    }

    function removeFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {
        if (_functionSelectors.length == 0) {
            revert NoSelectorsInFacetToCut();
        }
        MoreVaultsStorage storage ds = moreVaultsStorage();
        // if function does not exist then do nothing and return
        if (_facetAddress != address(0)) {
            revert ZeroAddress();
        }

        for (uint256 selectorIndex; selectorIndex < _functionSelectors.length;) {
            bytes4 selector = _functionSelectors[selectorIndex];
            address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;
            removeFunction(ds, oldFacetAddress, selector, false);
            unchecked {
                ++selectorIndex;
            }
        }
    }

    function addFacet(MoreVaultsStorage storage ds, address _facetAddress) internal {
        enforceHasContractCode(_facetAddress, "MoreVaultsLibCut: New facet has no code");
        ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds.facetAddresses.length;
        ds.facetAddresses.push(_facetAddress);
    }

    function addFunction(
        MoreVaultsStorage storage ds,
        bytes4 _selector,
        uint96 _selectorPosition,
        address _facetAddress
    ) internal {
        ds.selectorToFacetAndPosition[_selector].functionSelectorPosition = _selectorPosition;
        ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(_selector);
        ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;
    }

    function removeFunction(MoreVaultsStorage storage ds, address _facetAddress, bytes4 _selector, bool _isReplacing)
        internal
    {
        if (_facetAddress == address(0)) {
            revert FunctionDoesNotExist();
        }
        // an immutable function is a function defined directly in a diamond
        if (_facetAddress == address(this)) {
            revert ImmutableFunction();
        }
        // replace selector with last selector, then delete last selector
        uint256 selectorPosition = ds.selectorToFacetAndPosition[_selector].functionSelectorPosition;
        uint256 lastSelectorPosition = ds.facetFunctionSelectors[_facetAddress].functionSelectors.length - 1;
        // if not the same then replace _selector with lastSelector
        if (selectorPosition != lastSelectorPosition) {
            bytes4 lastSelector = ds.facetFunctionSelectors[_facetAddress].functionSelectors[lastSelectorPosition];
            ds.facetFunctionSelectors[_facetAddress].functionSelectors[selectorPosition] = lastSelector;
            ds.selectorToFacetAndPosition[lastSelector].functionSelectorPosition = uint96(selectorPosition);
        }

        // if no more selectors for facet address then delete the facet address
        if (lastSelectorPosition == 0) {
            // replace facet address with last facet address and delete last facet address
            uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;
            uint256 facetAddressPosition = ds.facetFunctionSelectors[_facetAddress].facetAddressPosition;
            if (facetAddressPosition != lastFacetAddressPosition) {
                address lastFacetAddress = ds.facetAddresses[lastFacetAddressPosition];
                ds.facetAddresses[facetAddressPosition] = lastFacetAddress;
                ds.facetFunctionSelectors[lastFacetAddress].facetAddressPosition = facetAddressPosition;
            }
            ds.facetAddresses.pop();
            delete ds
                .facetFunctionSelectors[_facetAddress]
                .facetAddressPosition;
            address factory = ds.factory;
            IVaultsFactory(factory).unlink(_facetAddress);

            (bool success, bytes memory result) = address(_facetAddress).delegatecall(
                abi.encodeWithSelector(
                    bytes4(IGenericMoreVaultFacetInitializable.onFacetRemoval.selector), _isReplacing
                )
            );
            // revert if onFacetRemoval exists on facet and failed
            if (!success && result.length > 0) {
                revert OnFacetRemovalFailed(_facetAddress, result);
            }
        }

        // delete the last selector
        ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();
        delete ds.selectorToFacetAndPosition[_selector];
    }

    function initializeAfterAddition(address _facetAddress, bytes memory _initData) internal {
        enforceHasContractCode(_facetAddress, "MoreVaultsLibCut: _facetAddress has no code");

        bytes memory callData =
            abi.encodeWithSelector(IGenericMoreVaultFacetInitializable.initialize.selector, _initData);
        (bool success, bytes memory error) = _facetAddress.delegatecall(callData);
        // 0x0dc149f0 is selector of error AlreadyInitialized()
        if (bytes4(error) == bytes4(hex"0dc149f0")) {
            return;
        }
        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(_facetAddress, callData);
            }
        }
    }

    function removeFromBeforeAccounting(MoreVaultsStorage storage ds, address _facetAddress, bool _isReplacing)
        internal
    {
        for (uint256 i; i < ds.beforeAccountingFacets.length;) {
            if (ds.beforeAccountingFacets[i] == _facetAddress) {
                if (!_isReplacing) {
                    (bool success,) =
                        address(_facetAddress).delegatecall(abi.encodeWithSelector(bytes4(BEFORE_ACCOUNTING_SELECTOR)));
                    assembly {
                        if iszero(success) {
                            mstore(0x40, BEFORE_ACCOUNTING_FAILED_ERROR)
                            mstore(add(0x40, 0x04), _facetAddress)
                            revert(0x40, 0x24)
                        }
                    }
                }
                ds.beforeAccountingFacets[i] = ds.beforeAccountingFacets[ds.beforeAccountingFacets.length - 1];
                ds.beforeAccountingFacets.pop();
                break;
            }
            unchecked {
                ++i;
            }
        }
    }

    function removeFromFacetsForAccounting(MoreVaultsStorage storage ds, bytes4 selector, bool _isReplacing) internal {
        for (uint256 i; i < ds.facetsForAccounting.length;) {
            if (ds.facetsForAccounting[i] == selector) {
                if (!_isReplacing) {
                    (bool success, bytes memory result) = address(this).staticcall(abi.encodeWithSelector(selector));
                    if (!success) {
                        revert AccountingFailed(selector);
                    }
                    uint256 decodedAmount = abi.decode(result, (uint256));
                    if (decodedAmount > 10e4) {
                        revert FacetHasBalance(decodedAmount);
                    }
                }
                ds.facetsForAccounting[i] = ds.facetsForAccounting[ds.facetsForAccounting.length - 1];
                ds.facetsForAccounting.pop();
                break;
            }
            unchecked {
                ++i;
            }
        }
    }

    function enforceHasContractCode(address _contract, string memory _errorMessage) internal view {
        uint256 contractSize;
        assembly {
            contractSize := extcodesize(_contract)
        }
        if (contractSize == 0) {
            revert ContractDoesntHaveCode(_errorMessage);
        }
    }

    function checkGasLimitOverflow() internal view {
        MoreVaultsStorage storage ds = moreVaultsStorage();

        GasLimit storage gl = ds.gasLimit;

        if (gl.value == 0) return;

        bytes32[] memory stakingIds = ds.vaultExternalAssets[TokenType.StakingToken].values();
        bytes32[] memory heldIds = ds.vaultExternalAssets[TokenType.HeldToken].values();

        uint256 stakingTokensLength;
        for (uint256 i = 0; i < stakingIds.length;) {
            unchecked {
                stakingTokensLength += ds.stakingAddresses[stakingIds[i]].length();
                ++i;
            }
        }

        uint256 tokensHeldLength;
        for (uint256 i = 0; i < heldIds.length;) {
            unchecked {
                tokensHeldLength += ds.tokensHeld[heldIds[i]].length();
                ++i;
            }
        }

        uint256 consumption;
        unchecked {
            consumption = tokensHeldLength * gl.heldTokenAccountingGas
                + stakingTokensLength * gl.stakingTokenAccountingGas
                + ds.availableAssets.length * gl.availableTokenAccountingGas
                + ds.facetsForAccounting.length * gl.facetAccountingGas + gl.nestedVaultsGas;
        }

        if (consumption > ds.gasLimit.value) {
            revert AccountingGasLimitExceeded(ds.gasLimit.value, consumption);
        }
    }

    function withdrawFromRequest(address _requester, uint256 _shares) internal returns (bool) {
        MoreVaultsStorage storage ds = moreVaultsStorage();
        WithdrawRequest storage request = ds.withdrawalRequests[_requester];
        // if withdrawal queue is disabled, request can be processed immediately
        if (!ds.isWithdrawalQueueEnabled) {
            // only allow for the shares owner to withdraw in this case
            return msg.sender == _requester;
        }

        if (isWithdrawableRequest(request.timelockEndsAt, ds.witdrawTimelock) && request.shares >= _shares) {
            request.shares -= _shares;
            return true;
        }

        return false;
    }

    function isWithdrawableRequest(uint256 _timelockEndsAt, uint256 _witdrawTimelock) private view returns (bool) {
        uint256 requestTimestamp = _timelockEndsAt - _witdrawTimelock;
        return block.timestamp >= _timelockEndsAt && block.timestamp - requestTimestamp <= MAX_WITHDRAWAL_DELAY;
    }

    function factoryAddress() internal view returns (address) {
        MoreVaultsStorage storage ds = moreVaultsStorage();
        return ds.factory;
    }

    function _setWhitelistFlag(bool isEnabled) internal {
        MoreVaultsStorage storage ds = moreVaultsStorage();
        ds.isWhitelistEnabled = isEnabled;
    }

    function _beforeAccounting(address[] storage _baf) internal {
        assembly {
            let freePtr := mload(0x40)
            let length := sload(_baf.slot)
            mstore(0, _baf.slot)
            let slot := keccak256(0, 0x20)
            mstore(freePtr, BEFORE_ACCOUNTING_SELECTOR)
            for { let i := 0 } lt(i, length) { i := add(i, 1) } {
                let facet := sload(add(slot, i))
                let res := delegatecall(gas(), facet, freePtr, 4, 0, 0) // call facets for acounting, ignore return values
                // if delegatecall fails, revert with the error
                if iszero(res) {
                    mstore(freePtr, BEFORE_ACCOUNTING_FAILED_ERROR)
                    mstore(add(freePtr, 0x04), facet)
                    revert(freePtr, 0x24)
                }
            }
        }
    }

    function _getCrossChainAccountingManager() internal view returns (address) {
        MoreVaultsStorage storage ds = moreVaultsStorage();
        AccessControlLib.AccessControlStorage storage acs = AccessControlLib.accessControlStorage();
        if (ds.crossChainAccountingManager == address(0)) {
            return IMoreVaultsRegistry(acs.moreVaultsRegistry).defaultCrossChainAccountingManager();
        }

        return ds.crossChainAccountingManager;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (utils/Pausable.sol)

pragma solidity ^0.8.20;

import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol";
import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol";

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract PausableUpgradeable is Initializable, ContextUpgradeable {
    /// @custom:storage-location erc7201:openzeppelin.storage.Pausable
    struct PausableStorage {
        bool _paused;
    }

    // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Pausable")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 private constant PausableStorageLocation = 0xcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300;

    function _getPausableStorage() private pure returns (PausableStorage storage $) {
        assembly {
            $.slot := PausableStorageLocation
        }
    }

    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    /**
     * @dev The operation failed because the contract is paused.
     */
    error EnforcedPause();

    /**
     * @dev The operation failed because the contract is not paused.
     */
    error ExpectedPause();

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        _requireNotPaused();
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        _requirePaused();
        _;
    }

    function __Pausable_init() internal onlyInitializing {
    }

    function __Pausable_init_unchained() internal onlyInitializing {
    }
    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        PausableStorage storage $ = _getPausableStorage();
        return $._paused;
    }

    /**
     * @dev Throws if the contract is paused.
     */
    function _requireNotPaused() internal view virtual {
        if (paused()) {
            revert EnforcedPause();
        }
    }

    /**
     * @dev Throws if the contract is not paused.
     */
    function _requirePaused() internal view virtual {
        if (!paused()) {
            revert ExpectedPause();
        }
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        PausableStorage storage $ = _getPausableStorage();
        $._paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        PausableStorage storage $ = _getPausableStorage();
        $._paused = false;
        emit Unpaused(_msgSender());
    }
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;

import {IERC4626} from "@openzeppelin/contracts/interfaces/IERC4626.sol";
import {IGenericMoreVaultFacetInitializable} from "./IGenericMoreVaultFacetInitializable.sol";

interface IVaultFacet is IERC4626, IGenericMoreVaultFacetInitializable {
    /// @dev Errors
    error BeforeAccountingFailed(address facet);
    error UnsupportedAsset(address);
    error ArraysLengthsDontMatch(uint256, uint256);
    error WithdrawFailed(string);
    error VaultDebtIsGreaterThanAssets();
    error NotAnERC4626CompatibleVault();    error WithdrawSchedulerInvalidTimestamp(uint256 timestamp);
    error CantCoverWithdrawRequests(uint256, uint256);
    error InvalidSharesAmount();
    error InvalidAssetsAmount();
    error CantProcessWithdrawRequest();
    error VaultIsUsingRestrictedFacet(address);
    error WithdrawalQueueDisabled();
    error NotAHub();
    error InvalidActionType();
    error OnlyCrossChainAccountingManager();
    error SyncActionsDisabledInThisVault();
    error RequestWasntFulfilled();
    error RequestWithdrawDisabled();

    /// @dev Events
    event Deposit(address indexed sender, address indexed owner, address[] tokens, uint256[] assets, uint256 shares);

    event AccrueInterest(uint256 newTotalAssets, uint256 interestAccrued);

    event WithdrawRequestCreated(address requester, uint256 sharesAmount, uint256 endsAt);

    event WithdrawRequestFulfilled(address requester, address receiver, uint256 sharesAmount, uint256 assetAmount);
    
    event WithdrawRequestDeleted(address requester);

    /// @notice Pauses all vault operations
    function pause() external;

    /// @notice Unpauses all vault operations
    function unpause() external;

    /// @notice Returns whether the contract is paused
    function paused() external view returns (bool);

    /// @notice Returns the total amount of the underlying asset that is "managed" by Vault
    function totalAssets() external view override returns (uint256);

    /// @notice Returns the total amount of the underlying asset that is "managed" by Vault in USD
    /// @return totalAssets The total amount of the underlying asset that is "managed" by Vault in USD
    /// @return success Whether the totalAssetsUsd calculation was successful
    function totalAssetsUsd() external returns (uint256, bool success);

    /// @notice Returns the request for a given owner
    /// @param _owner The owner of the request
    /// @return shares The shares of the request
    /// @return timelockEndsAt The timelock end time of the request
    function getWithdrawalRequest(address _owner) external view returns (uint256 shares, uint256 timelockEndsAt);

    /// @notice Allows deposit of multiple tokens in a single transaction
    /// @param tokens Array of token addresses to deposit
    /// @param assets Array of amounts to deposit for each token
    /// @param receiver Address that will receive the vault shares
    /// @return shares Amount of vault shares minted
    function deposit(address[] calldata tokens, uint256[] calldata assets, address receiver)
        external
        payable
        returns (uint256 shares);

    /// @notice Deposit a single asset for shares
    /// @param assets Amount of asset to deposit
    /// @param receiver Address that will receive the vault shares
    /// @return shares Amount of vault shares minted
    function deposit(uint256 assets, address receiver) external returns (uint256 shares);

    /// @notice Mint exact amount of shares by depositing assets
    /// @param shares Amount of shares to mint
    /// @param receiver Address that will receive the vault shares
    /// @return assets Amount of assets deposited
    function mint(uint256 shares, address receiver) external returns (uint256 assets);

    /// @notice Withdraw assets by burning shares
    /// @param assets Amount of assets to withdraw
    /// @param receiver Address that will receive the assets
    /// @param owner Owner of the shares
    /// @return shares Amount of shares burned
    function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);

    /// @notice Redeem shares for assets
    /// @param shares Amount of shares to redeem
    /// @param receiver Address that will receive the assets
    /// @param owner Owner of the shares
    /// @return assets Amount of assets withdrawn
    function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);

    /**
     * @notice Sets fee amount
     * @param fee New fee amount (in basis points, max 10000 = 100%)
     */
    function setFee(uint96 fee) external;

    /**
     * @notice Request a redeem of shares
     * @param shares Amount of shares to redeem
     */
    function requestRedeem(uint256 shares) external;

    /**
     * @notice Request a withdraw of assets
     * @param assets Amount of assets to withdraw
     */
    function requestWithdraw(uint256 assets) external;

    /**
     * @notice Clear a request
     */
    function clearRequest() external;
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC4626.sol)

pragma solidity >=0.6.2;

import {IERC20} from "../token/ERC20/IERC20.sol";
import {IERC20Metadata} from "../token/ERC20/extensions/IERC20Metadata.sol";

/**
 * @dev Interface of the ERC-4626 "Tokenized Vault Standard", as defined in
 * https://eips.ethereum.org/EIPS/eip-4626[ERC-4626].
 */
interface IERC4626 is IERC20, IERC20Metadata {
    event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);

    event Withdraw(
        address indexed sender,
        address indexed receiver,
        address indexed owner,
        uint256 assets,
        uint256 shares
    );

    /**
     * @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.
     *
     * - MUST be an ERC-20 token contract.
     * - MUST NOT revert.
     */
    function asset() external view returns (address assetTokenAddress);

    /**
     * @dev Returns the total amount of the underlying asset that is “managed” by Vault.
     *
     * - SHOULD include any compounding that occurs from yield.
     * - MUST be inclusive of any fees that are charged against assets in the Vault.
     * - MUST NOT revert.
     */
    function totalAssets() external view returns (uint256 totalManagedAssets);

    /**
     * @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal
     * scenario where all the conditions are met.
     *
     * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
     * - MUST NOT show any variations depending on the caller.
     * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
     * - MUST NOT revert.
     *
     * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
     * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
     * from.
     */
    function convertToShares(uint256 assets) external view returns (uint256 shares);

    /**
     * @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal
     * scenario where all the conditions are met.
     *
     * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
     * - MUST NOT show any variations depending on the caller.
     * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
     * - MUST NOT revert.
     *
     * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
     * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
     * from.
     */
    function convertToAssets(uint256 shares) external view returns (uint256 assets);

    /**
     * @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,
     * through a deposit call.
     *
     * - MUST return a limited value if receiver is subject to some deposit limit.
     * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.
     * - MUST NOT revert.
     */
    function maxDeposit(address receiver) external view returns (uint256 maxAssets);

    /**
     * @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given
     * current on-chain conditions.
     *
     * - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit
     *   call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called
     *   in the same transaction.
     * - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the
     *   deposit would be accepted, regardless if the user has enough tokens approved, etc.
     * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
     * - MUST NOT revert.
     *
     * NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in
     * share price or some other type of condition, meaning the depositor will lose assets by depositing.
     */
    function previewDeposit(uint256 assets) external view returns (uint256 shares);

    /**
     * @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.
     *
     * - MUST emit the Deposit event.
     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
     *   deposit execution, and are accounted for during deposit.
     * - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not
     *   approving enough underlying tokens to the Vault contract, etc).
     *
     * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
     */
    function deposit(uint256 assets, address receiver) external returns (uint256 shares);

    /**
     * @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.
     * - MUST return a limited value if receiver is subject to some mint limit.
     * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.
     * - MUST NOT revert.
     */
    function maxMint(address receiver) external view returns (uint256 maxShares);

    /**
     * @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given
     * current on-chain conditions.
     *
     * - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call
     *   in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the
     *   same transaction.
     * - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint
     *   would be accepted, regardless if the user has enough tokens approved, etc.
     * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
     * - MUST NOT revert.
     *
     * NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in
     * share price or some other type of condition, meaning the depositor will lose assets by minting.
     */
    function previewMint(uint256 shares) external view returns (uint256 assets);

    /**
     * @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.
     *
     * - MUST emit the Deposit event.
     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint
     *   execution, and are accounted for during mint.
     * - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not
     *   approving enough underlying tokens to the Vault contract, etc).
     *
     * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
     */
    function mint(uint256 shares, address receiver) external returns (uint256 assets);

    /**
     * @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the
     * Vault, through a withdraw call.
     *
     * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
     * - MUST NOT revert.
     */
    function maxWithdraw(address owner) external view returns (uint256 maxAssets);

    /**
     * @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,
     * given current on-chain conditions.
     *
     * - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw
     *   call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if
     *   called
     *   in the same transaction.
     * - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though
     *   the withdrawal would be accepted, regardless if the user has enough shares, etc.
     * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
     * - MUST NOT revert.
     *
     * NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in
     * share price or some other type of condition, meaning the depositor will lose assets by depositing.
     */
    function previewWithdraw(uint256 assets) external view returns (uint256 shares);

    /**
     * @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.
     *
     * - MUST emit the Withdraw event.
     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
     *   withdraw execution, and are accounted for during withdraw.
     * - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner
     *   not having enough shares, etc).
     *
     * Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
     * Those methods should be performed separately.
     */
    function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);

    /**
     * @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,
     * through a redeem call.
     *
     * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
     * - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.
     * - MUST NOT revert.
     */
    function maxRedeem(address owner) external view returns (uint256 maxShares);

    /**
     * @dev Allows an on-chain or off-chain user to simulate the effects of their redemption at the current block,
     * given current on-chain conditions.
     *
     * - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call
     *   in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the
     *   same transaction.
     * - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the
     *   redemption would be accepted, regardless if the user has enough shares, etc.
     * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
     * - MUST NOT revert.
     *
     * NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in
     * share price or some other type of condition, meaning the depositor will lose assets by redeeming.
     */
    function previewRedeem(uint256 shares) external view returns (uint256 assets);

    /**
     * @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.
     *
     * - MUST emit the Withdraw event.
     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
     *   redeem execution, and are accounted for during redeem.
     * - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner
     *   not having enough shares, etc).
     *
     * NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
     * Those methods should be performed separately.
     */
    function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);
}

// SPDX-License-Identifier: MIT

pragma solidity 0.8.28;

/**
 * @dev This is a base storage for the  initialization function for upgradeable diamond facet contracts
 *
 */
abstract contract BaseFacetInitializer {
    error InvalidParameters();
    error AlreadyInitialized();
    error FacetNotInitializing();

    struct Layout {
        /*
         * Indicates that the contract has been initialized.
         */
        bool _initialized;
        /*
         * Indicates that the contract is in the process of being initialized.
         */
        bool _initializing;
    }

    /**
     * @dev Returns the storage slot for this contract
     * @return bytes32 The storage slot
     */
    function INITIALIZABLE_STORAGE_SLOT() internal pure virtual returns (bytes32);

    function layoutInitializableStorage() internal pure returns (Layout storage l) {
        bytes32 slot = INITIALIZABLE_STORAGE_SLOT();
        assembly {
            l.slot := slot
        }
    }

    /**
     * @dev Modifier to protect an initializer function from being invoked twice.
     */
    modifier initializerFacet() {
        if (layoutInitializableStorage()._initializing ? !_isConstructor() : layoutInitializableStorage()._initialized)
        {
            revert AlreadyInitialized();
        }

        bool isTopLevelCall = !layoutInitializableStorage()._initializing;
        if (isTopLevelCall) {
            layoutInitializableStorage()._initializing = true;
            layoutInitializableStorage()._initialized = true;
        }

        _;

        if (isTopLevelCall) {
            layoutInitializableStorage()._initializing = false;
        }
    }

    /**
     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
     * {initializer} modifier, directly or indirectly.
     */
    modifier onlyInitializingFacet() {
        if (!layoutInitializableStorage()._initializing) {
            revert FacetNotInitializing();
        }
        _;
    }

    /// @dev Returns true if and only if the function is running in the constructor
    function _isConstructor() private view returns (bool) {
        // extcodesize checks the size of the code stored in an address, and
        // address returns the current address. Since the code is still not
        // deployed when running a constructor, any checks on its code size will
        // yield zero, making it an effective way to detect if a contract is
        // under construction or not.
        address self = address(this);
        uint256 cs;
        assembly {
            cs := extcodesize(self)
        }
        return cs == 0;
    }
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;

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

/**
 * @title IVaultRegistry
 * @notice Interface for VaultRegistry contract that manages allowed facets and their selectors
 */
interface IMoreVaultsRegistry {
    error ZeroAddress();
    error FacetAlreadyExists(address facet);
    error FacetNotAllowed(address facet);
    error SelectorAlreadyExists(address facet, bytes4 selector);

    struct ProtocolFeeInfo {
        address recipient;
        uint96 fee;
    }

    /**
     * @dev Emitted when new facet is added with its selectors
     * @param facet Address of added facet
     * @param selectors Array of function selectors
     */
    event FacetAdded(address indexed facet, bytes4[] selectors);

    /**
     * @dev Emitted when facet is edited
     * @param facet Address of edited facet
     * @param selectors Array of function selectors
     * @param addOrRemove Array with flags for add/remove of selector with same index
     */
    event FacetEdited(address indexed facet, bytes4[] selectors, bool[] addOrRemove);

    /**
     * @dev Emitted when facet is removed
     * @param facet Address of removed facet
     */
    event FacetRemoved(address indexed facet);

    /**
     * @dev Emitted when oracle registry address is updated
     * @param oldOracleRegistry Previous oracle registry address
     * @param newOracleRegistry New oracle registry address
     */
    event OracleRegistryUpdated(address indexed oldOracleRegistry, address indexed newOracleRegistry);

    /**
     * @dev Emitted when protocol fee info is updated
     * @param vault Address of the vault
     * @param recipient Address of the protocol fee recipient
     * @param fee Protocol fee
     */
    event ProtocolFeeInfoUpdated(address indexed vault, address indexed recipient, uint96 fee);

    /**
     * @dev Emitted when protocol is whitelisted
     * @param protocol Address of the protocol
     * @param whitelisted True if protocol is whitelisted, false otherwise
     */
    event AddressWhitelisted(address indexed protocol, bool whitelisted);

    /**
     * @dev Emitted when bridge is allowed
     * @param bridge Address of the bridge
     * @param allowed True if bridge is allowed, false otherwise
     */
    event BridgeUpdated(address indexed bridge, bool allowed);

    /**
     * @dev Emitted when cross chain accounting manager is updated
     * @param manager Address of the cross chain accounting manager
     * @param isManager True if cross chain accounting manager is allowed, false otherwise
     */
    event CrossChainAccountingManagerSet(address indexed manager, bool isManager);

    /**
     * @dev Emitted when default cross chain accounting manager is set
     * @param manager Address of the default cross chain accounting manager
     */
    event DefaultCrossChainAccountingManagerSet(address indexed manager);

    /**
     * @notice Initialize the registry
     * @param _owner Address of the owner
     * @param _oracle Address of the oracle
     * @param _usdStableTokenAddress Address of the USD stable token
     */
    function initialize(address _owner, address _oracle, address _usdStableTokenAddress) external;

    /**
     * @notice returns bool flag if registry is permissionless
     * @return bool flag if registry permissionless or not
     */
    function isPermissionless() external view returns (bool);

    /**
     * @notice Add new facet with its selectors, also can add new selectors to existing facet
     * @param facet Address of the facet contract
     * @param selectors Array of function selectors
     */
    function addFacet(address facet, bytes4[] calldata selectors) external;

    /**
     * @notice Edit selectors for the facet
     * @param facet Address of the facet contract
     * @param selectors Array of function selectors
     * @param addOrRemove Array with flags for add/remove of selector with same index
     */
    function editFacet(address facet, bytes4[] calldata selectors, bool[] calldata addOrRemove) external;

    /**
     * @notice Remove facet and all its selectors
     * @param facet Address of the facet contract
     */
    function removeFacet(address facet) external;

    /**
     * @notice Update oracle address
     * @param newOracleRegistry Address of new oracle registry
     */
    function updateOracleRegistry(address newOracleRegistry) external;

    /**
     * @notice Set protocol fee info
     * @param vault Address of the vault
     * @param recipient Address of the protocol fee recipient
     * @param fee Protocol fee
     */
    function setProtocolFeeInfo(address vault, address recipient, uint96 fee) external;

    /**
     * @notice Set selector allowed
     * @param vault Address of the vault
     * @param selector Function selector
     * @param allowed True if selector is allowed, false otherwise
     * @param mask Mask for the selector
     */
    function setSelectorAndMask(address vault, bytes4 selector, bool allowed, bytes memory mask) external;

    /**
     * @notice Set default cross chain accounting manager
     * @param manager Address of the default cross chain accounting manager
     */
    function setDefaultCrossChainAccountingManager(address manager) external;

    /**
     * @notice Set is cross chain accounting manager
     * @param manager Address of the cross chain accounting manager
     * @param isManager True if cross chain accounting manager is allowed, false otherwise
     */
    function setIsCrossChainAccountingManager(address manager, bool isManager) external;

    /**
     * @notice Get all selectors for facet
     * @param facet Address of the facet contract
     * @return Array of selectors
     */
    function getFacetSelectors(address facet) external view returns (bytes4[] memory);

    /**
     * @notice Get list of all allowed facets
     * @return Array of facet addresses
     */
    function getAllowedFacets() external view returns (address[] memory);

    /**
     * @notice Get protocol fee info
     * @param vault Address of the vault
     * @return address Address of the protocol fee recipient
     * @return uint96 Protocol fee
     */
    function protocolFeeInfo(address vault) external view returns (address, uint96);

    /**
     * @notice Get oracle address
     * @return IOracleRegistry Oracle registry contract
     */
    function oracle() external view returns (IOracleRegistry);

    /**
     * @notice Get facet address for selector
     * @param selector Function selector
     * @return address Facet address
     */
    function selectorToFacet(bytes4 selector) external view returns (address);

    /**
     * @notice Get facet address by index
     * @param index Index in facets list
     * @return address Facet address
     */
    function facetsList(uint256 index) external view returns (address);

    /**
     * @notice Get denomination asset decimals
     * @return uint8 Decimals of denomination asset
     */
    function getDenominationAssetDecimals() external view returns (uint8);

    /**
     * @notice Get denomination asset
     * @return address Denomination asset
     */
    function getDenominationAsset() external view returns (address);

    /**
     * @notice Check if facet is allowed
     * @param facet Address to check
     * @return bool True if facet is allowed
     */
    function isFacetAllowed(address facet) external view returns (bool);

    /**
     * @notice Add protocol to whitelist
     * @param protocol Address of the protocol
     */
    function addToWhitelist(address protocol) external;

    /**
     * @notice Remove protocol from whitelist
     * @param protocol Address of the protocol
     */
    function removeFromWhitelist(address protocol) external;

    /**
     * @notice Check if protocol is whitelisted
     * @param protocol Address of the protocol
     * @return bool True if protocol is whitelisted
     */
    function isWhitelisted(address protocol) external view returns (bool);

    /**
     * @notice Add bridge to allowed list
     * @param bridge Address of the bridge
     * @param allowed True if bridge is allowed, false otherwise
     */
    function setBridge(address bridge, bool allowed) external;

    /**
     * @notice Check if bridge is allowed
     * @param bridge Address of the bridge
     * @return bool True if bridge is allowed
     */
    function isBridgeAllowed(address bridge) external view returns (bool);

    /**
     * @notice Check if selector is allowed
     * @param vault Address of the vault
     * @param selector Function selector
     * @return bool True if selector is allowed
     * @return bytes Mask for the selector
     */
    function selectorInfo(address vault, bytes4 selector) external view returns (bool, bytes memory);

    /**
     * @notice Check if an address is a cross chain accounting manager
     * @param manager Address of the manager to check
     * @return bool True if the address is a cross chain accounting manager, false otherwise
     */
    function isCrossChainAccountingManager(address manager) external view returns (bool);

    /**
     * @notice Get default cross chain accounting manager
     * @return address Default cross chain accounting manager
     */
    function defaultCrossChainAccountingManager() external view returns (address);
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;

import {IMoreVaultsRegistry} from "./IMoreVaultsRegistry.sol";
import {IDiamondCut} from "./facets/IDiamondCut.sol";

interface IVaultsFactory {
    error InvalidSelector(address facet, bytes4 selector);
    error ZeroAddress();
    error EmptyFacets();
    error InvalidTimeLock();
    error InvalidFee();
    error ComposerInitializationFailed();

    event VaultDeployed(address indexed vault, address registry, address wrappedNative, IDiamondCut.FacetCut[] facets);

    event DiamondCutFacetUpdated(address indexed newDiamondCutFacet);
    event AccessControlFacetUpdated(address indexed newAccessControlFacet);
    event MaxFinalizationTimeUpdated(uint96 indexed newMaxFinalizationTime);
    event CrossChainLinkRequested(
        uint32 indexed dstChainId, address indexed initiator, address indexed vaultToLink, address remoteVault
    );
    event CrossChainLinked(uint32 indexed linkedVaultChainId, address indexed linkedVault, address indexed localVault);

    event SetFacetRestricted(address indexed _facet, bool indexed _isRestricted);
    event LzAdapterUpdated(address indexed newLzAdapter);
    event VaultComposerUpdated(address indexed vault, address indexed composer);
    event ComposerImplementationUpdated(address indexed newImplementation);
    event OFTAdapterFactoryUpdated(address indexed newOFTAdapterFactory);
    event VaultFailedToPause(address indexed vault);

    /**
     * @notice Initialize the factory
     * @param _owner Owner address
     * @param _registry Registry contract address
     * @param _diamondCutFacet Diamond cut facet address
     * @param _accessControlFacet Access control facet address
     * @param _wrappedNative Wrapped native token address
     * @param _localEid LayerZero endpoint id for this chain
     * @param _maxFinalizationTime Maximum finalization time of block for a chain
     * @param _lzAdapter LayerZero adapter address
     * @param _composerImplementation MoreVaultsComposer implementation address
     * @param _oftAdapterFactory OFT adapter factory address
     */
    function initialize(
        address _owner,
        address _registry,
        address _diamondCutFacet,
        address _accessControlFacet,
        address _wrappedNative,
        uint32 _localEid,
        uint96 _maxFinalizationTime,
        address _lzAdapter,
        address _composerImplementation,
        address _oftAdapterFactory
    ) external;

    /**
     * @notice Spoke requests registration on Hub
     */
    function requestRegisterSpoke(uint32 _hubEid, address _hubVault, address _spokeVault, bytes calldata _options)
        external
        payable;

    /**
     * @notice Get registry contract address
     * @return address Registry address
     */
    function registry() external view returns (IMoreVaultsRegistry);

    /**
     * @notice Check if vault was deployed by this factory
     * @param vault Address to check
     * @return bool True if vault was deployed by this factory
     */
    function isFactoryVault(address vault) external view returns (bool);

    /**
     * @notice Get vault by index
     * @param index Index of vault
     * @return address Vault address
     */
    function deployedVaults(uint256 index) external view returns (address);

    /**
     * @notice Deploy new vault instance
     * @param facetCuts Array of facets to add
     * @param accessControlFacetInitData encoded data that contains addresses of owner, curator and guardian
     * @return vault Address of deployed vault
     */
    function deployVault(
        IDiamondCut.FacetCut[] calldata facetCuts,
        bytes memory accessControlFacetInitData,
        bool isHub,
        bytes32 salt
    ) external returns (address vault);

    /**
     * @notice link the vault to the facet
     * @param facet address of the facet
     */
    function link(address facet) external;

    /**
     * @notice unlink the vault from the facet
     * @param facet address of the facet
     */
    function unlink(address facet) external;

    /**
     * @notice pauses all vaults using this facet
     * @param facet address of the facet
     */
    function pauseFacet(address facet) external;

    /**
     * @notice sets the lz adapter for the factory
     * @param lzAdapter address of the lz adapter
     */
    function setLzAdapter(address lzAdapter) external;

    /**
     * @notice sets the vault composer for a vault
     * @param vault address of the vault
     * @param composer address of the composer
     */
    function setVaultComposer(address vault, address composer) external;

    /**
     * @notice sets the composer implementation
     * @param composerImplementation address of the composer implementation
     */
    function setComposerImplementation(address composerImplementation) external;

    /**
     * @notice sets the OFT adapter factory
     * @param oftAdapterFactory address of the OFT adapter factory
     */
    function setOFTAdapterFactory(address oftAdapterFactory) external;

    /**
     * @notice sets restricted flag for facet
     * @param _facet address of facet
     * @param _isRestricted bool flag
     */
    function setFacetRestricted(address _facet, bool _isRestricted) external;

    /**
     * @notice Get all deployed vaults
     * @return Array of vault addresses
     */
    function getDeployedVaults() external view returns (address[] memory);

    /**
     * @notice Get number of deployed vaults
     * @return Number of vaults
     */
    function getVaultsCount() external view returns (uint256);

    /**
     * @notice Returns vaults addresses using this facet
     * @param _facet address of the facet
     */
    function getLinkedVaults(address _facet) external returns (address[] memory vaults);

    /**
     * @notice Returns bool flag if vault linked to the facet
     * @param _facet address of the facet
     * @param _vault address of the vault
     */
    function isVaultLinked(address _facet, address _vault) external returns (bool);

    /**
     * @notice Returns facet addresses that are restricted
     * @return facets addresses of the restricted facets
     */
    function getRestrictedFacets() external returns (address[] memory facets);

    /**
     * @notice Returns hub to spokes
     * @param _chainId chain id
     * @param _hubVault hub vault
     * @return eids endpoint ids of spokes
     * @return vaults addresses of spokes
     */
    function hubToSpokes(uint32 _chainId, address _hubVault)
        external
        view
        returns (uint32[] memory eids, address[] memory vaults);

    /**
     * @notice Returns spoke to hub
     * @param _chainId chain id
     * @param _spokeVault spoke vault
     * @return eid endpoint id of hub
     * @return vault address of hub vault
     */
    function spokeToHub(uint32 _chainId, address _spokeVault) external view returns (uint32 eid, address vault);

    /**
     * @notice Checks whether a hub has a given spoke linked
     * @param _hubEid Hub endpoint id
     * @param _hubVault Hub vault address
     * @param _spokeEid Spoke endpoint id
     * @param _spokeVault Spoke vault address
     * @return bool True if the spoke is linked to the hub
     */
    function isSpokeOfHub(uint32 _hubEid, address _hubVault, uint32 _spokeEid, address _spokeVault)
        external
        view
        returns (bool);

    /**
     * @notice Checks whether a vault is a cross-chain vault
     * @param _chainId Chain id
     * @param _vault Vault address
     * @return bool True if the vault is a cross-chain vault
     */
    function isCrossChainVault(uint32 _chainId, address _vault) external view returns (bool);

    /**
     * @notice Returns local EID
     * @return local EID
     */
    function localEid() external view returns (uint32);

    /**
     * @notice Returns vault composer for a vault
     * @param _vault Vault address
     * @return composer address of the composer
     */
    function vaultComposer(address _vault) external view returns (address);

    /**
     * @notice Returns LayerZero adapter address
     * @return LayerZero adapter address
     */
    function lzAdapter() external view returns (address);

    /**
     * @notice Returns MoreVaultsComposer implementation address
     * @return MoreVaultsComposer implementation address
     */
    function composerImplementation() external view returns (address);

    /**
     * @notice Returns OFT adapter factory address
     * @return OFT adapter factory address
     */
    function oftAdapterFactory() external view returns (address);

    /**
     * @notice Returns max finalization time
     * @return max finalization time
     */
    function maxFinalizationTime() external view returns (uint96);
}

File 9 of 41 : Math.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (utils/math/Math.sol)

pragma solidity ^0.8.20;

import {Panic} from "../Panic.sol";
import {SafeCast} from "./SafeCast.sol";

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Floor, // Toward negative infinity
        Ceil, // Toward positive infinity
        Trunc, // Toward zero
        Expand // Away from zero
    }

    /**
     * @dev Return the 512-bit addition of two uint256.
     *
     * The result is stored in two 256 variables such that sum = high * 2²⁵⁶ + low.
     */
    function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {
        assembly ("memory-safe") {
            low := add(a, b)
            high := lt(low, a)
        }
    }

    /**
     * @dev Return the 512-bit multiplication of two uint256.
     *
     * The result is stored in two 256 variables such that product = high * 2²⁵⁶ + low.
     */
    function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {
        // 512-bit multiply [high low] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use
        // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
        // variables such that product = high * 2²⁵⁶ + low.
        assembly ("memory-safe") {
            let mm := mulmod(a, b, not(0))
            low := mul(a, b)
            high := sub(sub(mm, low), lt(mm, low))
        }
    }

    /**
     * @dev Returns the addition of two unsigned integers, with a success flag (no overflow).
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
        unchecked {
            uint256 c = a + b;
            success = c >= a;
            result = c * SafeCast.toUint(success);
        }
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
        unchecked {
            uint256 c = a - b;
            success = c <= a;
            result = c * SafeCast.toUint(success);
        }
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
        unchecked {
            uint256 c = a * b;
            assembly ("memory-safe") {
                // Only true when the multiplication doesn't overflow
                // (c / a == b) || (a == 0)
                success := or(eq(div(c, a), b), iszero(a))
            }
            // equivalent to: success ? c : 0
            result = c * SafeCast.toUint(success);
        }
    }

    /**
     * @dev Returns the division of two unsigned integers, with a success flag (no division by zero).
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
        unchecked {
            success = b > 0;
            assembly ("memory-safe") {
                // The `DIV` opcode returns zero when the denominator is 0.
                result := div(a, b)
            }
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
        unchecked {
            success = b > 0;
            assembly ("memory-safe") {
                // The `MOD` opcode returns zero when the denominator is 0.
                result := mod(a, b)
            }
        }
    }

    /**
     * @dev Unsigned saturating addition, bounds to `2²⁵⁶ - 1` instead of overflowing.
     */
    function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) {
        (bool success, uint256 result) = tryAdd(a, b);
        return ternary(success, result, type(uint256).max);
    }

    /**
     * @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.
     */
    function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) {
        (, uint256 result) = trySub(a, b);
        return result;
    }

    /**
     * @dev Unsigned saturating multiplication, bounds to `2²⁵⁶ - 1` instead of overflowing.
     */
    function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {
        (bool success, uint256 result) = tryMul(a, b);
        return ternary(success, result, type(uint256).max);
    }

    /**
     * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.
     *
     * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.
     * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute
     * one branch when needed, making this function more expensive.
     */
    function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {
        unchecked {
            // branchless ternary works because:
            // b ^ (a ^ b) == a
            // b ^ 0 == b
            return b ^ ((a ^ b) * SafeCast.toUint(condition));
        }
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return ternary(a > b, a, b);
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return ternary(a < b, a, b);
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds towards infinity instead
     * of rounding towards zero.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        if (b == 0) {
            // Guarantee the same behavior as in a regular Solidity division.
            Panic.panic(Panic.DIVISION_BY_ZERO);
        }

        // The following calculation ensures accurate ceiling division without overflow.
        // Since a is non-zero, (a - 1) / b will not overflow.
        // The largest possible result occurs when (a - 1) / b is type(uint256).max,
        // but the largest value we can obtain is type(uint256).max - 1, which happens
        // when a = type(uint256).max and b = 1.
        unchecked {
            return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);
        }
    }

    /**
     * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
     * denominator == 0.
     *
     * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by
     * Uniswap Labs also under MIT license.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
        unchecked {
            (uint256 high, uint256 low) = mul512(x, y);

            // Handle non-overflow cases, 256 by 256 division.
            if (high == 0) {
                // Solidity will revert if denominator == 0, unlike the div opcode on its own.
                // The surrounding unchecked block does not change this fact.
                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
                return low / denominator;
            }

            // Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0.
            if (denominator <= high) {
                Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));
            }

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [high low].
            uint256 remainder;
            assembly ("memory-safe") {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                high := sub(high, gt(remainder, low))
                low := sub(low, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator.
            // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.

            uint256 twos = denominator & (0 - denominator);
            assembly ("memory-safe") {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [high low] by twos.
                low := div(low, twos)

                // Flip twos such that it is 2²⁵⁶ / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from high into low.
            low |= high * twos;

            // Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such
            // that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv ≡ 1 mod 2⁴.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also
            // works in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2⁸
            inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶
            inverse *= 2 - denominator * inverse; // inverse mod 2³²
            inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴
            inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸
            inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2²⁵⁶. Since the preconditions guarantee that the outcome is
            // less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and high
            // is no longer required.
            result = low * inverse;
            return result;
        }
    }

    /**
     * @dev Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
        return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);
    }

    /**
     * @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.
     */
    function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) {
        unchecked {
            (uint256 high, uint256 low) = mul512(x, y);
            if (high >= 1 << n) {
                Panic.panic(Panic.UNDER_OVERFLOW);
            }
            return (high << (256 - n)) | (low >> n);
        }
    }

    /**
     * @dev Calculates x * y >> n with full precision, following the selected rounding direction.
     */
    function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) {
        return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0);
    }

    /**
     * @dev Calculate the modular multiplicative inverse of a number in Z/nZ.
     *
     * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.
     * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.
     *
     * If the input value is not inversible, 0 is returned.
     *
     * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the
     * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.
     */
    function invMod(uint256 a, uint256 n) internal pure returns (uint256) {
        unchecked {
            if (n == 0) return 0;

            // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)
            // Used to compute integers x and y such that: ax + ny = gcd(a, n).
            // When the gcd is 1, then the inverse of a modulo n exists and it's x.
            // ax + ny = 1
            // ax = 1 + (-y)n
            // ax ≡ 1 (mod n) # x is the inverse of a modulo n

            // If the remainder is 0 the gcd is n right away.
            uint256 remainder = a % n;
            uint256 gcd = n;

            // Therefore the initial coefficients are:
            // ax + ny = gcd(a, n) = n
            // 0a + 1n = n
            int256 x = 0;
            int256 y = 1;

            while (remainder != 0) {
                uint256 quotient = gcd / remainder;

                (gcd, remainder) = (
                    // The old remainder is the next gcd to try.
                    remainder,
                    // Compute the next remainder.
                    // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd
                    // where gcd is at most n (capped to type(uint256).max)
                    gcd - remainder * quotient
                );

                (x, y) = (
                    // Increment the coefficient of a.
                    y,
                    // Decrement the coefficient of n.
                    // Can overflow, but the result is casted to uint256 so that the
                    // next value of y is "wrapped around" to a value between 0 and n - 1.
                    x - y * int256(quotient)
                );
            }

            if (gcd != 1) return 0; // No inverse exists.
            return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.
        }
    }

    /**
     * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.
     *
     * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is
     * prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that
     * `a**(p-2)` is the modular multiplicative inverse of a in Fp.
     *
     * NOTE: this function does NOT check that `p` is a prime greater than `2`.
     */
    function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {
        unchecked {
            return Math.modExp(a, p - 2, p);
        }
    }

    /**
     * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)
     *
     * Requirements:
     * - modulus can't be zero
     * - underlying staticcall to precompile must succeed
     *
     * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make
     * sure the chain you're using it on supports the precompiled contract for modular exponentiation
     * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,
     * the underlying function will succeed given the lack of a revert, but the result may be incorrectly
     * interpreted as 0.
     */
    function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {
        (bool success, uint256 result) = tryModExp(b, e, m);
        if (!success) {
            Panic.panic(Panic.DIVISION_BY_ZERO);
        }
        return result;
    }

    /**
     * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).
     * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying
     * to operate modulo 0 or if the underlying precompile reverted.
     *
     * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain
     * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in
     * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack
     * of a revert, but the result may be incorrectly interpreted as 0.
     */
    function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {
        if (m == 0) return (false, 0);
        assembly ("memory-safe") {
            let ptr := mload(0x40)
            // | Offset    | Content    | Content (Hex)                                                      |
            // |-----------|------------|--------------------------------------------------------------------|
            // | 0x00:0x1f | size of b  | 0x0000000000000000000000000000000000000000000000000000000000000020 |
            // | 0x20:0x3f | size of e  | 0x0000000000000000000000000000000000000000000000000000000000000020 |
            // | 0x40:0x5f | size of m  | 0x0000000000000000000000000000000000000000000000000000000000000020 |
            // | 0x60:0x7f | value of b | 0x<.............................................................b> |
            // | 0x80:0x9f | value of e | 0x<.............................................................e> |
            // | 0xa0:0xbf | value of m | 0x<.............................................................m> |
            mstore(ptr, 0x20)
            mstore(add(ptr, 0x20), 0x20)
            mstore(add(ptr, 0x40), 0x20)
            mstore(add(ptr, 0x60), b)
            mstore(add(ptr, 0x80), e)
            mstore(add(ptr, 0xa0), m)

            // Given the result < m, it's guaranteed to fit in 32 bytes,
            // so we can use the memory scratch space located at offset 0.
            success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)
            result := mload(0x00)
        }
    }

    /**
     * @dev Variant of {modExp} that supports inputs of arbitrary length.
     */
    function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {
        (bool success, bytes memory result) = tryModExp(b, e, m);
        if (!success) {
            Panic.panic(Panic.DIVISION_BY_ZERO);
        }
        return result;
    }

    /**
     * @dev Variant of {tryModExp} that supports inputs of arbitrary length.
     */
    function tryModExp(
        bytes memory b,
        bytes memory e,
        bytes memory m
    ) internal view returns (bool success, bytes memory result) {
        if (_zeroBytes(m)) return (false, new bytes(0));

        uint256 mLen = m.length;

        // Encode call args in result and move the free memory pointer
        result = abi.encodePacked(b.length, e.length, mLen, b, e, m);

        assembly ("memory-safe") {
            let dataPtr := add(result, 0x20)
            // Write result on top of args to avoid allocating extra memory.
            success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)
            // Overwrite the length.
            // result.length > returndatasize() is guaranteed because returndatasize() == m.length
            mstore(result, mLen)
            // Set the memory pointer after the returned data.
            mstore(0x40, add(dataPtr, mLen))
        }
    }

    /**
     * @dev Returns whether the provided byte array is zero.
     */
    function _zeroBytes(bytes memory byteArray) private pure returns (bool) {
        for (uint256 i = 0; i < byteArray.length; ++i) {
            if (byteArray[i] != 0) {
                return false;
            }
        }
        return true;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
     * towards zero.
     *
     * This method is based on Newton's method for computing square roots; the algorithm is restricted to only
     * using integer operations.
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        unchecked {
            // Take care of easy edge cases when a == 0 or a == 1
            if (a <= 1) {
                return a;
            }

            // In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a
            // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between
            // the current value as `ε_n = | x_n - sqrt(a) |`.
            //
            // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root
            // of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is
            // bigger than any uint256.
            //
            // By noticing that
            // `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)`
            // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar
            // to the msb function.
            uint256 aa = a;
            uint256 xn = 1;

            if (aa >= (1 << 128)) {
                aa >>= 128;
                xn <<= 64;
            }
            if (aa >= (1 << 64)) {
                aa >>= 64;
                xn <<= 32;
            }
            if (aa >= (1 << 32)) {
                aa >>= 32;
                xn <<= 16;
            }
            if (aa >= (1 << 16)) {
                aa >>= 16;
                xn <<= 8;
            }
            if (aa >= (1 << 8)) {
                aa >>= 8;
                xn <<= 4;
            }
            if (aa >= (1 << 4)) {
                aa >>= 4;
                xn <<= 2;
            }
            if (aa >= (1 << 2)) {
                xn <<= 1;
            }

            // We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1).
            //
            // We can refine our estimation by noticing that the middle of that interval minimizes the error.
            // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2).
            // This is going to be our x_0 (and ε_0)
            xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2)

            // From here, Newton's method give us:
            // x_{n+1} = (x_n + a / x_n) / 2
            //
            // One should note that:
            // x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a
            //              = ((x_n² + a) / (2 * x_n))² - a
            //              = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a
            //              = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²)
            //              = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²)
            //              = (x_n² - a)² / (2 * x_n)²
            //              = ((x_n² - a) / (2 * x_n))²
            //              ≥ 0
            // Which proves that for all n ≥ 1, sqrt(a) ≤ x_n
            //
            // This gives us the proof of quadratic convergence of the sequence:
            // ε_{n+1} = | x_{n+1} - sqrt(a) |
            //         = | (x_n + a / x_n) / 2 - sqrt(a) |
            //         = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) |
            //         = | (x_n - sqrt(a))² / (2 * x_n) |
            //         = | ε_n² / (2 * x_n) |
            //         = ε_n² / | (2 * x_n) |
            //
            // For the first iteration, we have a special case where x_0 is known:
            // ε_1 = ε_0² / | (2 * x_0) |
            //     ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2)))
            //     ≤ 2**(2*e-4) / (3 * 2**(e-1))
            //     ≤ 2**(e-3) / 3
            //     ≤ 2**(e-3-log2(3))
            //     ≤ 2**(e-4.5)
            //
            // For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n:
            // ε_{n+1} = ε_n² / | (2 * x_n) |
            //         ≤ (2**(e-k))² / (2 * 2**(e-1))
            //         ≤ 2**(2*e-2*k) / 2**e
            //         ≤ 2**(e-2*k)
            xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5)  -- special case, see above
            xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9)    -- general case with k = 4.5
            xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18)   -- general case with k = 9
            xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36)   -- general case with k = 18
            xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72)   -- general case with k = 36
            xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144)  -- general case with k = 72

            // Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision
            // ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either
            // sqrt(a) or sqrt(a) + 1.
            return xn - SafeCast.toUint(xn > a / xn);
        }
    }

    /**
     * @dev Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);
        }
    }

    /**
     * @dev Return the log in base 2 of a positive value rounded towards zero.
     * Returns 0 if given 0.
     */
    function log2(uint256 x) internal pure returns (uint256 r) {
        // If value has upper 128 bits set, log2 result is at least 128
        r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;
        // If upper 64 bits of 128-bit half set, add 64 to result
        r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;
        // If upper 32 bits of 64-bit half set, add 32 to result
        r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;
        // If upper 16 bits of 32-bit half set, add 16 to result
        r |= SafeCast.toUint((x >> r) > 0xffff) << 4;
        // If upper 8 bits of 16-bit half set, add 8 to result
        r |= SafeCast.toUint((x >> r) > 0xff) << 3;
        // If upper 4 bits of 8-bit half set, add 4 to result
        r |= SafeCast.toUint((x >> r) > 0xf) << 2;

        // Shifts value right by the current result and use it as an index into this lookup table:
        //
        // | x (4 bits) |  index  | table[index] = MSB position |
        // |------------|---------|-----------------------------|
        // |    0000    |    0    |        table[0] = 0         |
        // |    0001    |    1    |        table[1] = 0         |
        // |    0010    |    2    |        table[2] = 1         |
        // |    0011    |    3    |        table[3] = 1         |
        // |    0100    |    4    |        table[4] = 2         |
        // |    0101    |    5    |        table[5] = 2         |
        // |    0110    |    6    |        table[6] = 2         |
        // |    0111    |    7    |        table[7] = 2         |
        // |    1000    |    8    |        table[8] = 3         |
        // |    1001    |    9    |        table[9] = 3         |
        // |    1010    |   10    |        table[10] = 3        |
        // |    1011    |   11    |        table[11] = 3        |
        // |    1100    |   12    |        table[12] = 3        |
        // |    1101    |   13    |        table[13] = 3        |
        // |    1110    |   14    |        table[14] = 3        |
        // |    1111    |   15    |        table[15] = 3        |
        //
        // The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes.
        assembly ("memory-safe") {
            r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000))
        }
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);
        }
    }

    /**
     * @dev Return the log in base 10 of a positive value rounded towards zero.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10 ** 64) {
                value /= 10 ** 64;
                result += 64;
            }
            if (value >= 10 ** 32) {
                value /= 10 ** 32;
                result += 32;
            }
            if (value >= 10 ** 16) {
                value /= 10 ** 16;
                result += 16;
            }
            if (value >= 10 ** 8) {
                value /= 10 ** 8;
                result += 8;
            }
            if (value >= 10 ** 4) {
                value /= 10 ** 4;
                result += 4;
            }
            if (value >= 10 ** 2) {
                value /= 10 ** 2;
                result += 2;
            }
            if (value >= 10 ** 1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);
        }
    }

    /**
     * @dev Return the log in base 256 of a positive value rounded towards zero.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 x) internal pure returns (uint256 r) {
        // If value has upper 128 bits set, log2 result is at least 128
        r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;
        // If upper 64 bits of 128-bit half set, add 64 to result
        r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;
        // If upper 32 bits of 64-bit half set, add 32 to result
        r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;
        // If upper 16 bits of 32-bit half set, add 16 to result
        r |= SafeCast.toUint((x >> r) > 0xffff) << 4;
        // Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8
        return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);
    }

    /**
     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);
        }
    }

    /**
     * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
     */
    function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
        return uint8(rounding) % 2 == 1;
    }

    /**
     * @dev Counts the number of leading zero bits in a uint256.
     */
    function clz(uint256 x) internal pure returns (uint256) {
        return ternary(x == 0, 256, 255 - log2(x));
    }
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;

import {IDiamondCut} from "../interfaces/facets/IDiamondCut.sol";
import {IAccessControlFacet} from "../interfaces/facets/IAccessControlFacet.sol";
import {IConfigurationFacet} from "../interfaces/facets/IConfigurationFacet.sol";
import {IVaultFacet} from "../interfaces/facets/IVaultFacet.sol";

/**
 * @title AccessControlLib
 * @notice Library for managing access control in diamond proxy
 */
library AccessControlLib {
    /**
     * @dev Custom errors for access control
     */
    error UnauthorizedAccess();
    error ZeroAddress();
    error SameAddress();
    error NotPendingOwner();

    bytes32 constant ACCESS_CONTROL_STORAGE_POSITION = keccak256("MoreVaults.accessControl.storage");

    struct AccessControlStorage {
        address owner;
        address curator;
        address guardian;
        address moreVaultsRegistry;
        address pendingOwner;
    }

    /**
     * @dev Emitted when owner address is changed
     */
    event OwnerChanged(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Emitted when pending owner address is changed
     */
    event PendingOwnerSet(address indexed newPendingOwner);

    /**
     * @dev Emitted when curator address is changed
     */
    event CuratorChanged(address indexed previousCurator, address indexed newCurator);

    /**
     * @dev Emitted when guardian address is changed
     */
    event GuardianChanged(address indexed previousGuardian, address indexed newGuardian);

    /**
     * @dev Emitted when more vault registry address is changed
     */
    event MoreVaultRegistrySet(address indexed previousRegistry, address indexed newRegistry);

    function accessControlStorage() internal pure returns (AccessControlStorage storage acs) {
        bytes32 position = ACCESS_CONTROL_STORAGE_POSITION;
        // assigns struct storage slot to the storage position
        assembly {
            acs.slot := position
        }
    }

    /**
     * @notice Validates if caller is owner
     * @param caller Address to validate
     */
    function validateOwner(address caller) internal view {
        if (caller != accessControlStorage().owner) {
            revert UnauthorizedAccess();
        }
    }

    function validatePendingOwner(address caller) internal view {
        if (caller != accessControlStorage().pendingOwner) {
            revert UnauthorizedAccess();
        }
    }

    /**
     * @notice Validates if caller is curator
     * @param caller Address to validate
     */
    function validateCurator(address caller) internal view {
        if (caller != accessControlStorage().curator && accessControlStorage().owner != caller) {
            revert UnauthorizedAccess();
        }
    }

    /**
     * @notice Validates if caller is guardian or owner
     * @param caller Address to validate
     */
    function validateGuardian(address caller) internal view {
        if (accessControlStorage().guardian != caller) {
            revert UnauthorizedAccess();
        }
    }

    function validateDiamond(address caller) internal view {
        if (caller != address(this)) {
            revert UnauthorizedAccess();
        }
    }

    function validatePermissionForSelector(address caller, bytes4 selector) internal view {
        if (
            selector == IDiamondCut.diamondCut.selector || selector == IAccessControlFacet.transferOwnership.selector
                || selector == IAccessControlFacet.transferCuratorship.selector
                || selector == IAccessControlFacet.transferGuardian.selector
                || selector == IConfigurationFacet.disableDepositWhitelist.selector
                || selector == IConfigurationFacet.enableAssetToDeposit.selector
                || selector == IConfigurationFacet.setGasLimitForAccounting.selector
                || selector == IConfigurationFacet.setMaxSlippagePercent.selector
                || selector == IConfigurationFacet.setTimeLockPeriod.selector
                || selector == IConfigurationFacet.setWithdrawalTimelock.selector
                || selector == IConfigurationFacet.setWithdrawalFee.selector
                || selector == IConfigurationFacet.updateWithdrawalQueueStatus.selector
                || selector == IConfigurationFacet.setCrossChainAccountingManager.selector
                || selector == IVaultFacet.setFee.selector
        ) {
            validateOwner(caller);
        } else {
            validateCurator(caller);
        }
    }

    function setPendingOwner(address _newPendingOwner) internal {
        if (_newPendingOwner == accessControlStorage().owner) {
            revert SameAddress();
        }

        accessControlStorage().pendingOwner = _newPendingOwner;

        emit PendingOwnerSet(_newPendingOwner);
    }

    /**
     * @notice Sets new owner address
     * @param _newOwner Address of new owner
     */
    function setVaultOwner(address _newOwner) internal {
        if (_newOwner == address(0)) {
            revert ZeroAddress();
        }

        AccessControlStorage storage acs = accessControlStorage();

        if (_newOwner == acs.owner) {
            revert SameAddress();
        }

        address previousOwner = acs.owner;
        acs.owner = _newOwner;

        emit OwnerChanged(previousOwner, _newOwner);
    }

    /**
     * @notice Sets new curator address
     * @param _newCurator Address of new curator
     */
    function setVaultCurator(address _newCurator) internal {
        if (_newCurator == address(0)) {
            revert ZeroAddress();
        }

        AccessControlStorage storage acs = accessControlStorage();

        if (_newCurator == acs.curator) {
            revert SameAddress();
        }

        address previousCurator = acs.curator;
        acs.curator = _newCurator;

        emit CuratorChanged(previousCurator, _newCurator);
    }

    /**
     * @notice Sets new guardian address
     * @param _newGuardian Address of new guardian
     */
    function setVaultGuardian(address _newGuardian) internal {
        if (_newGuardian == address(0)) {
            revert ZeroAddress();
        }

        AccessControlStorage storage acs = accessControlStorage();

        if (_newGuardian == acs.guardian) {
            revert SameAddress();
        }

        address previousGuardian = acs.guardian;
        acs.guardian = _newGuardian;

        emit GuardianChanged(previousGuardian, _newGuardian);
    }

    function setMoreVaultsRegistry(address _newRegistry) internal {
        if (_newRegistry == address(0)) {
            revert ZeroAddress();
        }

        AccessControlStorage storage acs = accessControlStorage();

        if (_newRegistry == acs.moreVaultsRegistry) {
            revert SameAddress();
        }

        acs.moreVaultsRegistry = _newRegistry;
    }

    /**
     * @notice Gets current owner address
     * @return Address of current owner
     */
    function vaultOwner() internal view returns (address) {
        return accessControlStorage().owner;
    }

    function pendingOwner() internal view returns (address) {
        return accessControlStorage().pendingOwner;
    }

    /**
     * @notice Gets current curator address
     * @return Address of current curator
     */
    function vaultCurator() internal view returns (address) {
        return accessControlStorage().curator;
    }

    /**
     * @notice Gets current guardian address
     * @return Address of current guardian
     */
    function vaultGuardian() internal view returns (address) {
        return accessControlStorage().guardian;
    }

    /**
     * @notice Gets current more vault registry address
     * @return Address of current more vault registry
     */
    function vaultRegistry() internal view returns (address) {
        return accessControlStorage().moreVaultsRegistry;
    }

    function setVaultRegistry(address newRegistry) internal {
        if (newRegistry == address(0)) {
            revert ZeroAddress();
        }
        AccessControlStorage storage acs = accessControlStorage();
        address previousRegistry = acs.moreVaultsRegistry;
        acs.moreVaultsRegistry = newRegistry;

        emit MoreVaultRegistrySet(previousRegistry, newRegistry);
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {IVaultsFactory} from "./IVaultsFactory.sol";
import {
    MessagingReceipt,
    MessagingFee
} from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol";

/// @title IBridgeAdapter - Common interface for bridge adapters
interface IBridgeAdapter {
    /**
     * @notice Common errors
     */
    error InvalidAmount();
    error InvalidDestChain();
    error UnauthorizedVault();
    error NotEnoughFee();
    error InsufficientBalance();
    error InsufficientAllowance();
    error ChainPaused();
    error UntrustedOFT();
    error ZeroAddress();
    error ArrayLengthMismatch();
    error InvalidOFTToken();
    error InvalidLayerZeroEid();
    error NoResponses();
    error UnsupportedChain(uint32 chainId);
    error InvalidBridgeParams();
    error NativeTransferFailed();
    error InvalidReceiver(uint32, address);
    error InvalidAddress();
    error SlippageTooHigh();
    error InvalidVault();
    error InsufficientMsgValue(uint256 expectedMsgValue, uint256 actualMsgValue);

    /**
     * @notice Shared events (each adapter has its own specific BridgeExecuted event)
     */
    event EidPaused(uint32 indexed eid);
    event EidUnpaused(uint32 indexed eid);

    /**
     * @notice Quote fee for read operation
     * @param vaults Array of vault addresses
     * @param eids Array of LayerZero EIDs
     * @param _extraOptions Extra options for the read operation
     * @return fee The fee for the read operation
     */
    function quoteReadFee(address[] memory vaults, uint32[] memory eids, bytes calldata _extraOptions)
        external
        view
        returns (MessagingFee memory fee);

    /**
     * @notice Execute a cross-chain bridge operation
     * @param bridgeSpecificParams Encoded parameters specific to the bridge implementation
     * @dev Implementation should emit BridgeExecuted event
     */
    function executeBridging(bytes calldata bridgeSpecificParams) external payable;

    /**
     * @notice Initiate a cross-chain accounting operation
     * @param vaults Array of vault addresses
     * @param eids Array of LayerZero EIDs
     * @param _extraOptions Extra options for the cross-chain accounting operation
     * @param _initiator The initiator of the cross-chain accounting operation
     * @return receipt The receipt of the cross-chain accounting operation
     */
    function initiateCrossChainAccounting(
        address[] memory vaults,
        uint32[] memory eids,
        bytes calldata _extraOptions,
        address _initiator
    ) external payable returns (MessagingReceipt memory receipt);

    /**
     * @notice Set the LayerZero read channel
     * @param _channelId The channel ID to set
     * @param _active Whether the channel is active
     */
    function setReadChannel(uint32 _channelId, bool _active) external;

    /**
     * @notice Emergency token rescue (admin only)
     * @param token Token to rescue
     * @param to Recipient address
     * @param amount Amount to rescue
     */
    function rescueToken(address token, address payable to, uint256 amount) external;

    /**
     * @notice Get quote for bridge operation
     * @param bridgeSpecificParams Encoded parameters specific to the bridge implementation
     * @return nativeFee The native token fee required for the bridge operation
     */
    function quoteBridgeFee(bytes calldata bridgeSpecificParams) external view returns (uint256 nativeFee);

    /**
     * @notice Pause/unpause bridge operations (admin only)
     */
    function pause() external;
    function unpause() external;
    function paused() external view returns (bool);

    /**
     * @notice Set slippage (admin only)
     * @param newSlippageBps New slippage in basis points
     */
    function setSlippage(uint256 newSlippageBps) external;

    // EID-only pausing API
    function pauseEid(uint32 eid) external;
    function unpauseEid(uint32 eid) external;
    function isEidPaused(uint32 eid) external view returns (bool);

    /**
     * @notice Batch set trust status for multiple OFT tokens
     * @param ofts Array of OFT token addresses
     * @param trusted Array of trust statuses (must match ofts length)
     * @dev Moved from VaultsRegistry to adapter for better separation of concerns
     *      Protected against reentrancy in implementations
     */
    function setTrustedOFTs(address[] calldata ofts, bool[] calldata trusted) external;

    /**
     * @notice Check if an OFT token is trusted for bridging
     * @param oft Address of the OFT token to check
     * @return bool True if the token is trusted, false otherwise
     */
    function isTrustedOFT(address oft) external view returns (bool);

    /**
     * @notice Get all trusted OFT tokens
     * @return address[] Array of trusted OFT addresses
     */
    function getTrustedOFTs() external view returns (address[] memory);
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.10;

import {IAggregatorV2V3Interface} from "../interfaces/Chainlink/IAggregatorV2V3Interface.sol";

/**
 * @title IOracleRegistry
 * @author MORE Labs
 * @notice Interface for the OracleRegistry contract to get asset prices and manage price sources
 */
interface IOracleRegistry {
    error PriceIsNotAvailable();
    error InconsistentParamsLength();
    error OraclePriceIsOld();
    error AggregatorNotSet();

    /**
     * @notice Struct describing the asset price source and staleness threshold
     * @param aggregator The Chainlink aggregator interface for the asset
     * @param stalenessThreshold The maximum allowed staleness for the price data
     */
    struct OracleInfo {
        IAggregatorV2V3Interface aggregator;
        uint96 stalenessThreshold;
    }

    /**
     * @notice Emitted when the base currency is set
     * @param baseCurrency The address of the base currency
     * @param baseCurrencyUnit The unit of the base currency
     */
    event BaseCurrencySet(address indexed baseCurrency, uint256 baseCurrencyUnit);

    /**
     * @notice Emitted when an asset source is updated
     * @param asset The address of the asset
     * @param info The new OracleInfo struct for the asset
     */
    event OracleInfoUpdated(address indexed asset, OracleInfo info);

    event SpokeOracleInfoUpdated(address indexed hub, uint32 indexed chaindId, OracleInfo info);

    /**
     * @notice Returns the base currency address used for price quotes
     * @return The address of the base currency (e.g., 0x0 for USD)
     */
    function BASE_CURRENCY() external view returns (address);

    /**
     * @notice Returns the unit of the base currency
     * @return The unit of the base currency (e.g., 1e8 for USD)
     */
    function BASE_CURRENCY_UNIT() external view returns (uint256);

    /**
     * @notice Sets the price sources for a list of assets
     * @dev Only callable by accounts with the ORACLE_MANAGER_ROLE
     * @param assets The addresses of the assets
     * @param infos The OracleInfo struct for each asset
     */
    function setOracleInfos(address[] calldata assets, OracleInfo[] calldata infos) external;

    function setSpokeOracleInfos(address hub, uint32[] calldata chainIds, OracleInfo[] calldata infos) external;

    function getSpokeValue(address hub, uint32 chainId) external view returns (uint256);

    function getSpokeOracleInfo(address hub, uint32 chainId) external view returns (OracleInfo memory);

    /**
     * @notice Returns the price of a given asset
     * @param asset The address of the asset
     * @return The price of the asset in the base currency
     */
    function getAssetPrice(address asset) external view returns (uint256);

    /**
     * @notice Returns the prices of a list of assets
     * @param assets The addresses of the assets
     * @return An array of prices for each asset in the base currency
     */
    function getAssetsPrices(address[] calldata assets) external view returns (uint256[] memory);

    /**
     * @notice Returns the OracleInfo struct for a given asset
     * @param asset The address of the asset
     * @return The OracleInfo struct containing aggregator and staleness threshold
     */
    function getOracleInfo(address asset) external view returns (OracleInfo memory);
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;

import {MoreVaultsLib} from "../../libraries/MoreVaultsLib.sol";
import {IGenericMoreVaultFacetInitializable} from "./IGenericMoreVaultFacetInitializable.sol";

/**
 * @title IBridgeFacet
 * @dev Interface for the bridge facet providing cross-chain functionality for vaults
 * @notice This interface defines methods for managing cross-chain operations between hub and spoke vaults
 */
interface IBridgeFacet is IGenericMoreVaultFacetInitializable {
    error CrossChainRequestWasntFulfilled(bytes32);
    error InvalidActionType();
    error OnlyCrossChainAccountingManager();
    error RequestWasntFulfilled();
    error FinalizationCallFailed();
    error OracleWasntSetForSpoke(address, uint32);
    error NoOracleForSpoke(uint32);
    error AlreadySet();
    error AccountingViaOracles();
    error AdapterNotAllowed(address);
    error RequestTimedOut();
    error RequestAlreadyFinalized();
    error NotEnoughMsgValueProvided();

    /**
     * @dev Returns the sum of assets from all spoke vaults in USD
     * @return sum Sum of assets from all spoke vaults
     * @return isPositive Flag indicating that the value is positive
     * @notice Used for calculating the total value of assets in cross-chain vault
     */
    function accountingBridgeFacet() external view returns (uint256 sum, bool isPositive);

    /**
     * @dev Enables or disables the use of oracles for cross-chain accounting
     * @param isTrue true to enable oracles, false to disable
     * @notice Only the owner can call this function
     * @notice When enabling, checks for the presence of oracles for all spoke chains
     */
    function setOraclesCrossChainAccounting(bool isTrue) external;

    /**
     * @dev Quotes the native fee required to initiate cross-chain accounting
     * @param extraOptions Additional options for the cross-chain read (adapter-specific)
     * @return nativeFee The estimated native token fee required
     */
    function quoteAccountingFee(bytes calldata extraOptions) external view returns (uint256 nativeFee);

    /**
     * @dev Executes a cross-chain bridge operation
     * @param adapter Address of the adapter to use
     * @param token Address of the token to bridge
     * @param amount Amount of the token to bridge
     * @param bridgeSpecificParams Bridge-specific parameters
     */
    function executeBridging(address adapter, address token, uint256 amount, bytes calldata bridgeSpecificParams)
        external
        payable;

    /**
     * @dev Initiates a request to perform an action in a cross-chain vault
     * @param actionType Type of action to perform (deposit, withdraw, mint, etc.)
     * @param actionCallData Action call data
     * @param extraOptions Additional options for cross-chain transfer
     * @return guid Unique request number for tracking
     * @notice Function requires gas payment for cross-chain transfer
     * @notice Available only when the contract is not paused
     */
    function initVaultActionRequest(
        MoreVaultsLib.ActionType actionType,
        bytes calldata actionCallData,
        bytes calldata extraOptions
    ) external payable returns (bytes32 guid);

    /**
     * @dev Updates accounting information for a request
     * @param guid Request number to update
     * @param sumOfSpokesUsdValue Sum of USD value of all spoke vaults
     * @param readSuccess Flag indicating if the read operation was successful
     * @notice Can only be called by the cross-chain accounting manager
     * @notice Updates total assets and marks the request as fulfilled
     */
    function updateAccountingInfoForRequest(bytes32 guid, uint256 sumOfSpokesUsdValue, bool readSuccess) external;

    /**
     * @dev Finalizes the execution of a cross-chain request
     * @param guid Request number to finalize
     * @notice Executes the actual action after receiving all data from spoke vaults
     * @notice Supports various action types: deposit, withdraw, mint, set fee
     * @notice Can only be called after successful accounting information update
     */
    function finalizeRequest(bytes32 guid) external payable returns (bytes memory result);

    /**
     * @dev Returns the request info for a given guid
     * @param guid Request number to get info for
     * @return Request info
     */
    function getRequestInfo(bytes32 guid) external view returns (MoreVaultsLib.CrossChainRequestInfo memory);
}

File 14 of 41 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC20.sol)

pragma solidity >=0.4.16;

import {IERC20} from "../token/ERC20/IERC20.sol";

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../IERC20.sol";
import {IERC1363} from "../../../interfaces/IERC1363.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC-20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    /**
     * @dev An operation with an ERC-20 token failed.
     */
    error SafeERC20FailedOperation(address token);

    /**
     * @dev Indicates a failed `decreaseAllowance` request.
     */
    error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);

    /**
     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        if (!_safeTransfer(token, to, value, true)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
     */
    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        if (!_safeTransferFrom(token, from, to, value, true)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.
     */
    function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {
        return _safeTransfer(token, to, value, false);
    }

    /**
     * @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.
     */
    function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {
        return _safeTransferFrom(token, from, to, value, false);
    }

    /**
     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     *
     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
     * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
     */
    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 oldAllowance = token.allowance(address(this), spender);
        forceApprove(token, spender, oldAllowance + value);
    }

    /**
     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
     * value, non-reverting calls are assumed to be successful.
     *
     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
     * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
     */
    function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
        unchecked {
            uint256 currentAllowance = token.allowance(address(this), spender);
            if (currentAllowance < requestedDecrease) {
                revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
            }
            forceApprove(token, spender, currentAllowance - requestedDecrease);
        }
    }

    /**
     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
     * to be set to zero before setting it to a non-zero value, such as USDT.
     *
     * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function
     * only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being
     * set here.
     */
    function forceApprove(IERC20 token, address spender, uint256 value) internal {
        if (!_safeApprove(token, spender, value, false)) {
            if (!_safeApprove(token, spender, 0, true)) revert SafeERC20FailedOperation(address(token));
            if (!_safeApprove(token, spender, value, true)) revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no
     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * Reverts if the returned value is other than `true`.
     */
    function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
        if (to.code.length == 0) {
            safeTransfer(token, to, value);
        } else if (!token.transferAndCall(to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target
     * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * Reverts if the returned value is other than `true`.
     */
    function transferFromAndCallRelaxed(
        IERC1363 token,
        address from,
        address to,
        uint256 value,
        bytes memory data
    ) internal {
        if (to.code.length == 0) {
            safeTransferFrom(token, from, to, value);
        } else if (!token.transferFromAndCall(from, to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no
     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.
     * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}
     * once without retrying, and relies on the returned value to be true.
     *
     * Reverts if the returned value is other than `true`.
     */
    function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
        if (to.code.length == 0) {
            forceApprove(token, to, value);
        } else if (!token.approveAndCall(to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Imitates a Solidity `token.transfer(to, value)` call, relaxing the requirement on the return value: the
     * return value is optional (but if data is returned, it must not be false).
     *
     * @param token The token targeted by the call.
     * @param to The recipient of the tokens
     * @param value The amount of token to transfer
     * @param bubble Behavior switch if the transfer call reverts: bubble the revert reason or return a false boolean.
     */
    function _safeTransfer(IERC20 token, address to, uint256 value, bool bubble) private returns (bool success) {
        bytes4 selector = IERC20.transfer.selector;

        assembly ("memory-safe") {
            let fmp := mload(0x40)
            mstore(0x00, selector)
            mstore(0x04, and(to, shr(96, not(0))))
            mstore(0x24, value)
            success := call(gas(), token, 0, 0x00, 0x44, 0x00, 0x20)
            // if call success and return is true, all is good.
            // otherwise (not success or return is not true), we need to perform further checks
            if iszero(and(success, eq(mload(0x00), 1))) {
                // if the call was a failure and bubble is enabled, bubble the error
                if and(iszero(success), bubble) {
                    returndatacopy(fmp, 0x00, returndatasize())
                    revert(fmp, returndatasize())
                }
                // if the return value is not true, then the call is only successful if:
                // - the token address has code
                // - the returndata is empty
                success := and(success, and(iszero(returndatasize()), gt(extcodesize(token), 0)))
            }
            mstore(0x40, fmp)
        }
    }

    /**
     * @dev Imitates a Solidity `token.transferFrom(from, to, value)` call, relaxing the requirement on the return
     * value: the return value is optional (but if data is returned, it must not be false).
     *
     * @param token The token targeted by the call.
     * @param from The sender of the tokens
     * @param to The recipient of the tokens
     * @param value The amount of token to transfer
     * @param bubble Behavior switch if the transfer call reverts: bubble the revert reason or return a false boolean.
     */
    function _safeTransferFrom(
        IERC20 token,
        address from,
        address to,
        uint256 value,
        bool bubble
    ) private returns (bool success) {
        bytes4 selector = IERC20.transferFrom.selector;

        assembly ("memory-safe") {
            let fmp := mload(0x40)
            mstore(0x00, selector)
            mstore(0x04, and(from, shr(96, not(0))))
            mstore(0x24, and(to, shr(96, not(0))))
            mstore(0x44, value)
            success := call(gas(), token, 0, 0x00, 0x64, 0x00, 0x20)
            // if call success and return is true, all is good.
            // otherwise (not success or return is not true), we need to perform further checks
            if iszero(and(success, eq(mload(0x00), 1))) {
                // if the call was a failure and bubble is enabled, bubble the error
                if and(iszero(success), bubble) {
                    returndatacopy(fmp, 0x00, returndatasize())
                    revert(fmp, returndatasize())
                }
                // if the return value is not true, then the call is only successful if:
                // - the token address has code
                // - the returndata is empty
                success := and(success, and(iszero(returndatasize()), gt(extcodesize(token), 0)))
            }
            mstore(0x40, fmp)
            mstore(0x60, 0)
        }
    }

    /**
     * @dev Imitates a Solidity `token.approve(spender, value)` call, relaxing the requirement on the return value:
     * the return value is optional (but if data is returned, it must not be false).
     *
     * @param token The token targeted by the call.
     * @param spender The spender of the tokens
     * @param value The amount of token to transfer
     * @param bubble Behavior switch if the transfer call reverts: bubble the revert reason or return a false boolean.
     */
    function _safeApprove(IERC20 token, address spender, uint256 value, bool bubble) private returns (bool success) {
        bytes4 selector = IERC20.approve.selector;

        assembly ("memory-safe") {
            let fmp := mload(0x40)
            mstore(0x00, selector)
            mstore(0x04, and(spender, shr(96, not(0))))
            mstore(0x24, value)
            success := call(gas(), token, 0, 0x00, 0x44, 0x00, 0x20)
            // if call success and return is true, all is good.
            // otherwise (not success or return is not true), we need to perform further checks
            if iszero(and(success, eq(mload(0x00), 1))) {
                // if the call was a failure and bubble is enabled, bubble the error
                if and(iszero(success), bubble) {
                    returndatacopy(fmp, 0x00, returndatasize())
                    revert(fmp, returndatasize())
                }
                // if the return value is not true, then the call is only successful if:
                // - the token address has code
                // - the returndata is empty
                success := and(success, and(iszero(returndatasize()), gt(extcodesize(token), 0)))
            }
            mstore(0x40, fmp)
        }
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol)

pragma solidity ^0.8.20;

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

/**
 * @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 EIP-1153 (transient storage) is available on the chain you're deploying at,
 * consider using {ReentrancyGuardTransient} instead.
 *
 * 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].
 *
 * IMPORTANT: Deprecated. This storage-based reentrancy guard will be removed and replaced
 * by the {ReentrancyGuardTransient} variant in v6.0.
 *
 * @custom:stateless
 */
abstract contract ReentrancyGuard {
    using StorageSlot for bytes32;

    // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ReentrancyGuard")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 private constant REENTRANCY_GUARD_STORAGE =
        0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00;

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

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

    constructor() {
        _reentrancyGuardStorageSlot().getUint256Slot().value = 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();
    }

    /**
     * @dev A `view` only version of {nonReentrant}. Use to block view functions
     * from being called, preventing reading from inconsistent contract state.
     *
     * CAUTION: This is a "view" modifier and does not change the reentrancy
     * status. Use it only on view functions. For payable or non-payable functions,
     * use the standard {nonReentrant} modifier instead.
     */
    modifier nonReentrantView() {
        _nonReentrantBeforeView();
        _;
    }

    function _nonReentrantBeforeView() private view {
        if (_reentrancyGuardEntered()) {
            revert ReentrancyGuardReentrantCall();
        }
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be NOT_ENTERED
        _nonReentrantBeforeView();

        // Any calls to nonReentrant after this point will fail
        _reentrancyGuardStorageSlot().getUint256Slot().value = ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _reentrancyGuardStorageSlot().getUint256Slot().value = 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 _reentrancyGuardStorageSlot().getUint256Slot().value == ENTERED;
    }

    function _reentrancyGuardStorageSlot() internal pure virtual returns (bytes32) {
        return REENTRANCY_GUARD_STORAGE;
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0;

import { IMessageLibManager } from "./IMessageLibManager.sol";
import { IMessagingComposer } from "./IMessagingComposer.sol";
import { IMessagingChannel } from "./IMessagingChannel.sol";
import { IMessagingContext } from "./IMessagingContext.sol";

struct MessagingParams {
    uint32 dstEid;
    bytes32 receiver;
    bytes message;
    bytes options;
    bool payInLzToken;
}

struct MessagingReceipt {
    bytes32 guid;
    uint64 nonce;
    MessagingFee fee;
}

struct MessagingFee {
    uint256 nativeFee;
    uint256 lzTokenFee;
}

struct Origin {
    uint32 srcEid;
    bytes32 sender;
    uint64 nonce;
}

interface ILayerZeroEndpointV2 is IMessageLibManager, IMessagingComposer, IMessagingChannel, IMessagingContext {
    event PacketSent(bytes encodedPayload, bytes options, address sendLibrary);

    event PacketVerified(Origin origin, address receiver, bytes32 payloadHash);

    event PacketDelivered(Origin origin, address receiver);

    event LzReceiveAlert(
        address indexed receiver,
        address indexed executor,
        Origin origin,
        bytes32 guid,
        uint256 gas,
        uint256 value,
        bytes message,
        bytes extraData,
        bytes reason
    );

    event LzTokenSet(address token);

    event DelegateSet(address sender, address delegate);

    function quote(MessagingParams calldata _params, address _sender) external view returns (MessagingFee memory);

    function send(
        MessagingParams calldata _params,
        address _refundAddress
    ) external payable returns (MessagingReceipt memory);

    function verify(Origin calldata _origin, address _receiver, bytes32 _payloadHash) external;

    function verifiable(Origin calldata _origin, address _receiver) external view returns (bool);

    function initializable(Origin calldata _origin, address _receiver) external view returns (bool);

    function lzReceive(
        Origin calldata _origin,
        address _receiver,
        bytes32 _guid,
        bytes calldata _message,
        bytes calldata _extraData
    ) external payable;

    // oapp can burn messages partially by calling this function with its own business logic if messages are verified in order
    function clear(address _oapp, Origin calldata _origin, bytes32 _guid, bytes calldata _message) external;

    function setLzToken(address _lzToken) external;

    function lzToken() external view returns (address);

    function nativeToken() external view returns (address);

    function setDelegate(address _delegate) external;
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;

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

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

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

    /// @notice Add/replace/remove any number of functions and optionally execute
    ///         a function with delegatecall
    /// @param _diamondCut Contains the facet addresses and function selectors
    function diamondCut(FacetCut[] calldata _diamondCut) external;

    event DiamondCut(FacetCut[] _diamondCut);
}

File 19 of 41 : EnumerableSet.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.

pragma solidity ^0.8.20;

import {Arrays} from "../Arrays.sol";
import {Math} from "../math/Math.sol";

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 * - Set can be cleared (all elements removed) in O(n).
 *
 * ```solidity
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * The following types are supported:
 *
 * - `bytes32` (`Bytes32Set`) since v3.3.0
 * - `address` (`AddressSet`) since v3.3.0
 * - `uint256` (`UintSet`) since v3.3.0
 * - `string` (`StringSet`) since v5.4.0
 * - `bytes` (`BytesSet`) since v5.4.0
 *
 * [WARNING]
 * ====
 * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
 * unusable.
 * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
 *
 * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
 * array of EnumerableSet.
 * ====
 */
library EnumerableSet {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

    struct Set {
        // Storage of set values
        bytes32[] _values;
        // Position is the index of the value in the `values` array plus 1.
        // Position 0 is used to mean a value is not in the set.
        mapping(bytes32 value => uint256) _positions;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function _add(Set storage set, bytes32 value) private returns (bool) {
        if (!_contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._positions[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function _remove(Set storage set, bytes32 value) private returns (bool) {
        // We cache the value's position to prevent multiple reads from the same storage slot
        uint256 position = set._positions[value];

        if (position != 0) {
            // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 valueIndex = position - 1;
            uint256 lastIndex = set._values.length - 1;

            if (valueIndex != lastIndex) {
                bytes32 lastValue = set._values[lastIndex];

                // Move the lastValue to the index where the value to delete is
                set._values[valueIndex] = lastValue;
                // Update the tracked position of the lastValue (that was just moved)
                set._positions[lastValue] = position;
            }

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the tracked position for the deleted slot
            delete set._positions[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes all the values from a set. O(n).
     *
     * WARNING: This function has an unbounded cost that scales with set size. Developers should keep in mind that
     * using it may render the function uncallable if the set grows to the point where clearing it consumes too much
     * gas to fit in a block.
     */
    function _clear(Set storage set) private {
        uint256 len = _length(set);
        for (uint256 i = 0; i < len; ++i) {
            delete set._positions[set._values[i]];
        }
        Arrays.unsafeSetLength(set._values, 0);
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function _contains(Set storage set, bytes32 value) private view returns (bool) {
        return set._positions[value] != 0;
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function _length(Set storage set) private view returns (uint256) {
        return set._values.length;
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function _at(Set storage set, uint256 index) private view returns (bytes32) {
        return set._values[index];
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function _values(Set storage set) private view returns (bytes32[] memory) {
        return set._values;
    }

    /**
     * @dev Return a slice of the set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function _values(Set storage set, uint256 start, uint256 end) private view returns (bytes32[] memory) {
        unchecked {
            end = Math.min(end, _length(set));
            start = Math.min(start, end);

            uint256 len = end - start;
            bytes32[] memory result = new bytes32[](len);
            for (uint256 i = 0; i < len; ++i) {
                result[i] = Arrays.unsafeAccess(set._values, start + i).value;
            }
            return result;
        }
    }

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _add(set._inner, value);
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _remove(set._inner, value);
    }

    /**
     * @dev Removes all the values from a set. O(n).
     *
     * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
     * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.
     */
    function clear(Bytes32Set storage set) internal {
        _clear(set._inner);
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
        return _contains(set._inner, value);
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(Bytes32Set storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
        return _at(set._inner, index);
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
        bytes32[] memory store = _values(set._inner);
        bytes32[] memory result;

        assembly ("memory-safe") {
            result := store
        }

        return result;
    }

    /**
     * @dev Return a slice of the set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(Bytes32Set storage set, uint256 start, uint256 end) internal view returns (bytes32[] memory) {
        bytes32[] memory store = _values(set._inner, start, end);
        bytes32[] memory result;

        assembly ("memory-safe") {
            result := store
        }

        return result;
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(AddressSet storage set, address value) internal returns (bool) {
        return _add(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(AddressSet storage set, address value) internal returns (bool) {
        return _remove(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Removes all the values from a set. O(n).
     *
     * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
     * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.
     */
    function clear(AddressSet storage set) internal {
        _clear(set._inner);
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(AddressSet storage set, address value) internal view returns (bool) {
        return _contains(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(AddressSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(AddressSet storage set, uint256 index) internal view returns (address) {
        return address(uint160(uint256(_at(set._inner, index))));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(AddressSet storage set) internal view returns (address[] memory) {
        bytes32[] memory store = _values(set._inner);
        address[] memory result;

        assembly ("memory-safe") {
            result := store
        }

        return result;
    }

    /**
     * @dev Return a slice of the set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(AddressSet storage set, uint256 start, uint256 end) internal view returns (address[] memory) {
        bytes32[] memory store = _values(set._inner, start, end);
        address[] memory result;

        assembly ("memory-safe") {
            result := store
        }

        return result;
    }

    // UintSet

    struct UintSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(UintSet storage set, uint256 value) internal returns (bool) {
        return _add(set._inner, bytes32(value));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(UintSet storage set, uint256 value) internal returns (bool) {
        return _remove(set._inner, bytes32(value));
    }

    /**
     * @dev Removes all the values from a set. O(n).
     *
     * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
     * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.
     */
    function clear(UintSet storage set) internal {
        _clear(set._inner);
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(UintSet storage set, uint256 value) internal view returns (bool) {
        return _contains(set._inner, bytes32(value));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(UintSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(UintSet storage set, uint256 index) internal view returns (uint256) {
        return uint256(_at(set._inner, index));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(UintSet storage set) internal view returns (uint256[] memory) {
        bytes32[] memory store = _values(set._inner);
        uint256[] memory result;

        assembly ("memory-safe") {
            result := store
        }

        return result;
    }

    /**
     * @dev Return a slice of the set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(UintSet storage set, uint256 start, uint256 end) internal view returns (uint256[] memory) {
        bytes32[] memory store = _values(set._inner, start, end);
        uint256[] memory result;

        assembly ("memory-safe") {
            result := store
        }

        return result;
    }

    struct StringSet {
        // Storage of set values
        string[] _values;
        // Position is the index of the value in the `values` array plus 1.
        // Position 0 is used to mean a value is not in the set.
        mapping(string value => uint256) _positions;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(StringSet storage set, string memory value) internal returns (bool) {
        if (!contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._positions[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(StringSet storage set, string memory value) internal returns (bool) {
        // We cache the value's position to prevent multiple reads from the same storage slot
        uint256 position = set._positions[value];

        if (position != 0) {
            // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 valueIndex = position - 1;
            uint256 lastIndex = set._values.length - 1;

            if (valueIndex != lastIndex) {
                string memory lastValue = set._values[lastIndex];

                // Move the lastValue to the index where the value to delete is
                set._values[valueIndex] = lastValue;
                // Update the tracked position of the lastValue (that was just moved)
                set._positions[lastValue] = position;
            }

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the tracked position for the deleted slot
            delete set._positions[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes all the values from a set. O(n).
     *
     * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
     * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.
     */
    function clear(StringSet storage set) internal {
        uint256 len = length(set);
        for (uint256 i = 0; i < len; ++i) {
            delete set._positions[set._values[i]];
        }
        Arrays.unsafeSetLength(set._values, 0);
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(StringSet storage set, string memory value) internal view returns (bool) {
        return set._positions[value] != 0;
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function length(StringSet storage set) internal view returns (uint256) {
        return set._values.length;
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(StringSet storage set, uint256 index) internal view returns (string memory) {
        return set._values[index];
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(StringSet storage set) internal view returns (string[] memory) {
        return set._values;
    }

    /**
     * @dev Return a slice of the set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(StringSet storage set, uint256 start, uint256 end) internal view returns (string[] memory) {
        unchecked {
            end = Math.min(end, length(set));
            start = Math.min(start, end);

            uint256 len = end - start;
            string[] memory result = new string[](len);
            for (uint256 i = 0; i < len; ++i) {
                result[i] = Arrays.unsafeAccess(set._values, start + i).value;
            }
            return result;
        }
    }

    struct BytesSet {
        // Storage of set values
        bytes[] _values;
        // Position is the index of the value in the `values` array plus 1.
        // Position 0 is used to mean a value is not in the set.
        mapping(bytes value => uint256) _positions;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(BytesSet storage set, bytes memory value) internal returns (bool) {
        if (!contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._positions[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(BytesSet storage set, bytes memory value) internal returns (bool) {
        // We cache the value's position to prevent multiple reads from the same storage slot
        uint256 position = set._positions[value];

        if (position != 0) {
            // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 valueIndex = position - 1;
            uint256 lastIndex = set._values.length - 1;

            if (valueIndex != lastIndex) {
                bytes memory lastValue = set._values[lastIndex];

                // Move the lastValue to the index where the value to delete is
                set._values[valueIndex] = lastValue;
                // Update the tracked position of the lastValue (that was just moved)
                set._positions[lastValue] = position;
            }

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the tracked position for the deleted slot
            delete set._positions[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes all the values from a set. O(n).
     *
     * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
     * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.
     */
    function clear(BytesSet storage set) internal {
        uint256 len = length(set);
        for (uint256 i = 0; i < len; ++i) {
            delete set._positions[set._values[i]];
        }
        Arrays.unsafeSetLength(set._values, 0);
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(BytesSet storage set, bytes memory value) internal view returns (bool) {
        return set._positions[value] != 0;
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function length(BytesSet storage set) internal view returns (uint256) {
        return set._values.length;
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(BytesSet storage set, uint256 index) internal view returns (bytes memory) {
        return set._values[index];
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(BytesSet storage set) internal view returns (bytes[] memory) {
        return set._values;
    }

    /**
     * @dev Return a slice of the set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(BytesSet storage set, uint256 start, uint256 end) internal view returns (bytes[] memory) {
        unchecked {
            end = Math.min(end, length(set));
            start = Math.min(start, end);

            uint256 len = end - start;
            bytes[] memory result = new bytes[](len);
            for (uint256 i = 0; i < len; ++i) {
                result[i] = Arrays.unsafeAccess(set._values, start + i).value;
            }
            return result;
        }
    }
}

// SPDX-License-Identifier: AGPL-3.0
pragma solidity 0.8.28;

// solhint-disable-next-line interface-starts-with-i
interface IAggregatorV2V3Interface {
    function decimals() external view returns (uint8);

    function description() external view returns (string memory);

    function version() external view returns (uint256);

    function latestAnswer() external view returns (int256);

    function latestTimestamp() external view returns (uint256);

    function latestRound() external view returns (uint256);

    function getAnswer(uint256 roundId) external view returns (int256);

    function getTimestamp(uint256 roundId) external view returns (uint256);

    event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt);

    event NewRound(uint256 indexed roundId, address indexed startedBy, uint256 startedAt);

    function getRoundData(uint80 _roundId)
        external
        view
        returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);

    function latestRoundData()
        external
        view
        returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity >=0.6.2;

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

/**
 * @dev Interface for the optional metadata functions from the ERC-20 standard.
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;

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

interface IGenericMoreVaultFacetInitializable is IGenericMoreVaultFacet {
    function initialize(bytes calldata data) external;

    function onFacetRemoval(bool isReplacing) external;
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;
import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol";

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract ContextUpgradeable is Initializable {
    function __Context_init() internal onlyInitializing {
    }

    function __Context_init_unchained() internal onlyInitializing {
    }
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (proxy/utils/Initializable.sol)

pragma solidity ^0.8.20;

/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
 * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
 * case an upgrade adds a module that needs to be initialized.
 *
 * For example:
 *
 * [.hljs-theme-light.nopadding]
 * ```solidity
 * contract MyToken is ERC20Upgradeable {
 *     function initialize() initializer public {
 *         __ERC20_init("MyToken", "MTK");
 *     }
 * }
 *
 * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
 *     function initializeV2() reinitializer(2) public {
 *         __ERC20Permit_init("MyToken");
 *     }
 * }
 * ```
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 *
 * [CAUTION]
 * ====
 * Avoid leaving a contract uninitialized.
 *
 * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
 * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
 * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
 *
 * [.hljs-theme-light.nopadding]
 * ```
 * /// @custom:oz-upgrades-unsafe-allow constructor
 * constructor() {
 *     _disableInitializers();
 * }
 * ```
 * ====
 */
abstract contract Initializable {
    /**
     * @dev Storage of the initializable contract.
     *
     * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions
     * when using with upgradeable contracts.
     *
     * @custom:storage-location erc7201:openzeppelin.storage.Initializable
     */
    struct InitializableStorage {
        /**
         * @dev Indicates that the contract has been initialized.
         */
        uint64 _initialized;
        /**
         * @dev Indicates that the contract is in the process of being initialized.
         */
        bool _initializing;
    }

    // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;

    /**
     * @dev The contract is already initialized.
     */
    error InvalidInitialization();

    /**
     * @dev The contract is not initializing.
     */
    error NotInitializing();

    /**
     * @dev Triggered when the contract has been initialized or reinitialized.
     */
    event Initialized(uint64 version);

    /**
     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
     * `onlyInitializing` functions can be used to initialize parent contracts.
     *
     * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any
     * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in
     * production.
     *
     * Emits an {Initialized} event.
     */
    modifier initializer() {
        // solhint-disable-next-line var-name-mixedcase
        InitializableStorage storage $ = _getInitializableStorage();

        // Cache values to avoid duplicated sloads
        bool isTopLevelCall = !$._initializing;
        uint64 initialized = $._initialized;

        // Allowed calls:
        // - initialSetup: the contract is not in the initializing state and no previous version was
        //                 initialized
        // - construction: the contract is initialized at version 1 (no reinitialization) and the
        //                 current contract is just being deployed
        bool initialSetup = initialized == 0 && isTopLevelCall;
        bool construction = initialized == 1 && address(this).code.length == 0;

        if (!initialSetup && !construction) {
            revert InvalidInitialization();
        }
        $._initialized = 1;
        if (isTopLevelCall) {
            $._initializing = true;
        }
        _;
        if (isTopLevelCall) {
            $._initializing = false;
            emit Initialized(1);
        }
    }

    /**
     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
     * used to initialize parent contracts.
     *
     * A reinitializer may be used after the original initialization step. This is essential to configure modules that
     * are added through upgrades and that require initialization.
     *
     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
     * cannot be nested. If one is invoked in the context of another, execution will revert.
     *
     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
     * a contract, executing them in the right order is up to the developer or operator.
     *
     * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.
     *
     * Emits an {Initialized} event.
     */
    modifier reinitializer(uint64 version) {
        // solhint-disable-next-line var-name-mixedcase
        InitializableStorage storage $ = _getInitializableStorage();

        if ($._initializing || $._initialized >= version) {
            revert InvalidInitialization();
        }
        $._initialized = version;
        $._initializing = true;
        _;
        $._initializing = false;
        emit Initialized(version);
    }

    /**
     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
     * {initializer} and {reinitializer} modifiers, directly or indirectly.
     */
    modifier onlyInitializing() {
        _checkInitializing();
        _;
    }

    /**
     * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.
     */
    function _checkInitializing() internal view virtual {
        if (!_isInitializing()) {
            revert NotInitializing();
        }
    }

    /**
     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called
     * through proxies.
     *
     * Emits an {Initialized} event the first time it is successfully executed.
     */
    function _disableInitializers() internal virtual {
        // solhint-disable-next-line var-name-mixedcase
        InitializableStorage storage $ = _getInitializableStorage();

        if ($._initializing) {
            revert InvalidInitialization();
        }
        if ($._initialized != type(uint64).max) {
            $._initialized = type(uint64).max;
            emit Initialized(type(uint64).max);
        }
    }

    /**
     * @dev Returns the highest version that has been initialized. See {reinitializer}.
     */
    function _getInitializedVersion() internal view returns (uint64) {
        return _getInitializableStorage()._initialized;
    }

    /**
     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
     */
    function _isInitializing() internal view returns (bool) {
        return _getInitializableStorage()._initializing;
    }

    /**
     * @dev Pointer to storage slot. Allows integrators to override it with a custom storage location.
     *
     * NOTE: Consider following the ERC-7201 formula to derive storage locations.
     */
    function _initializableStorageSlot() internal pure virtual returns (bytes32) {
        return INITIALIZABLE_STORAGE;
    }

    /**
     * @dev Returns a pointer to the storage namespace.
     */
    // solhint-disable-next-line var-name-mixedcase
    function _getInitializableStorage() private pure returns (InitializableStorage storage $) {
        bytes32 slot = _initializableStorageSlot();
        assembly {
            $.slot := slot
        }
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol)

pragma solidity >=0.4.16;

/**
 * @dev Interface of the ERC-20 standard as defined in the ERC.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the value of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 value) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 value) external returns (bool);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)

pragma solidity ^0.8.20;

/**
 * @dev Helper library for emitting standardized panic codes.
 *
 * ```solidity
 * contract Example {
 *      using Panic for uint256;
 *
 *      // Use any of the declared internal constants
 *      function foo() { Panic.GENERIC.panic(); }
 *
 *      // Alternatively
 *      function foo() { Panic.panic(Panic.GENERIC); }
 * }
 * ```
 *
 * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].
 *
 * _Available since v5.1._
 */
// slither-disable-next-line unused-state
library Panic {
    /// @dev generic / unspecified error
    uint256 internal constant GENERIC = 0x00;
    /// @dev used by the assert() builtin
    uint256 internal constant ASSERT = 0x01;
    /// @dev arithmetic underflow or overflow
    uint256 internal constant UNDER_OVERFLOW = 0x11;
    /// @dev division or modulo by zero
    uint256 internal constant DIVISION_BY_ZERO = 0x12;
    /// @dev enum conversion error
    uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;
    /// @dev invalid encoding in storage
    uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;
    /// @dev empty array pop
    uint256 internal constant EMPTY_ARRAY_POP = 0x31;
    /// @dev array out of bounds access
    uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;
    /// @dev resource error (too large allocation or too large array)
    uint256 internal constant RESOURCE_ERROR = 0x41;
    /// @dev calling invalid internal function
    uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;

    /// @dev Reverts with a panic code. Recommended to use with
    /// the internal constants with predefined codes.
    function panic(uint256 code) internal pure {
        assembly ("memory-safe") {
            mstore(0x00, 0x4e487b71)
            mstore(0x20, code)
            revert(0x1c, 0x24)
        }
    }
}

File 27 of 41 : SafeCast.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)
// This file was procedurally generated from scripts/generate/templates/SafeCast.js.

pragma solidity ^0.8.20;

/**
 * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow
 * checks.
 *
 * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
 * easily result in undesired exploitation or bugs, since developers usually
 * assume that overflows raise errors. `SafeCast` restores this intuition by
 * reverting the transaction when such an operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeCast {
    /**
     * @dev Value doesn't fit in an uint of `bits` size.
     */
    error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);

    /**
     * @dev An int value doesn't fit in an uint of `bits` size.
     */
    error SafeCastOverflowedIntToUint(int256 value);

    /**
     * @dev Value doesn't fit in an int of `bits` size.
     */
    error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);

    /**
     * @dev An uint value doesn't fit in an int of `bits` size.
     */
    error SafeCastOverflowedUintToInt(uint256 value);

    /**
     * @dev Returns the downcasted uint248 from uint256, reverting on
     * overflow (when the input is greater than largest uint248).
     *
     * Counterpart to Solidity's `uint248` operator.
     *
     * Requirements:
     *
     * - input must fit into 248 bits
     */
    function toUint248(uint256 value) internal pure returns (uint248) {
        if (value > type(uint248).max) {
            revert SafeCastOverflowedUintDowncast(248, value);
        }
        return uint248(value);
    }

    /**
     * @dev Returns the downcasted uint240 from uint256, reverting on
     * overflow (when the input is greater than largest uint240).
     *
     * Counterpart to Solidity's `uint240` operator.
     *
     * Requirements:
     *
     * - input must fit into 240 bits
     */
    function toUint240(uint256 value) internal pure returns (uint240) {
        if (value > type(uint240).max) {
            revert SafeCastOverflowedUintDowncast(240, value);
        }
        return uint240(value);
    }

    /**
     * @dev Returns the downcasted uint232 from uint256, reverting on
     * overflow (when the input is greater than largest uint232).
     *
     * Counterpart to Solidity's `uint232` operator.
     *
     * Requirements:
     *
     * - input must fit into 232 bits
     */
    function toUint232(uint256 value) internal pure returns (uint232) {
        if (value > type(uint232).max) {
            revert SafeCastOverflowedUintDowncast(232, value);
        }
        return uint232(value);
    }

    /**
     * @dev Returns the downcasted uint224 from uint256, reverting on
     * overflow (when the input is greater than largest uint224).
     *
     * Counterpart to Solidity's `uint224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     */
    function toUint224(uint256 value) internal pure returns (uint224) {
        if (value > type(uint224).max) {
            revert SafeCastOverflowedUintDowncast(224, value);
        }
        return uint224(value);
    }

    /**
     * @dev Returns the downcasted uint216 from uint256, reverting on
     * overflow (when the input is greater than largest uint216).
     *
     * Counterpart to Solidity's `uint216` operator.
     *
     * Requirements:
     *
     * - input must fit into 216 bits
     */
    function toUint216(uint256 value) internal pure returns (uint216) {
        if (value > type(uint216).max) {
            revert SafeCastOverflowedUintDowncast(216, value);
        }
        return uint216(value);
    }

    /**
     * @dev Returns the downcasted uint208 from uint256, reverting on
     * overflow (when the input is greater than largest uint208).
     *
     * Counterpart to Solidity's `uint208` operator.
     *
     * Requirements:
     *
     * - input must fit into 208 bits
     */
    function toUint208(uint256 value) internal pure returns (uint208) {
        if (value > type(uint208).max) {
            revert SafeCastOverflowedUintDowncast(208, value);
        }
        return uint208(value);
    }

    /**
     * @dev Returns the downcasted uint200 from uint256, reverting on
     * overflow (when the input is greater than largest uint200).
     *
     * Counterpart to Solidity's `uint200` operator.
     *
     * Requirements:
     *
     * - input must fit into 200 bits
     */
    function toUint200(uint256 value) internal pure returns (uint200) {
        if (value > type(uint200).max) {
            revert SafeCastOverflowedUintDowncast(200, value);
        }
        return uint200(value);
    }

    /**
     * @dev Returns the downcasted uint192 from uint256, reverting on
     * overflow (when the input is greater than largest uint192).
     *
     * Counterpart to Solidity's `uint192` operator.
     *
     * Requirements:
     *
     * - input must fit into 192 bits
     */
    function toUint192(uint256 value) internal pure returns (uint192) {
        if (value > type(uint192).max) {
            revert SafeCastOverflowedUintDowncast(192, value);
        }
        return uint192(value);
    }

    /**
     * @dev Returns the downcasted uint184 from uint256, reverting on
     * overflow (when the input is greater than largest uint184).
     *
     * Counterpart to Solidity's `uint184` operator.
     *
     * Requirements:
     *
     * - input must fit into 184 bits
     */
    function toUint184(uint256 value) internal pure returns (uint184) {
        if (value > type(uint184).max) {
            revert SafeCastOverflowedUintDowncast(184, value);
        }
        return uint184(value);
    }

    /**
     * @dev Returns the downcasted uint176 from uint256, reverting on
     * overflow (when the input is greater than largest uint176).
     *
     * Counterpart to Solidity's `uint176` operator.
     *
     * Requirements:
     *
     * - input must fit into 176 bits
     */
    function toUint176(uint256 value) internal pure returns (uint176) {
        if (value > type(uint176).max) {
            revert SafeCastOverflowedUintDowncast(176, value);
        }
        return uint176(value);
    }

    /**
     * @dev Returns the downcasted uint168 from uint256, reverting on
     * overflow (when the input is greater than largest uint168).
     *
     * Counterpart to Solidity's `uint168` operator.
     *
     * Requirements:
     *
     * - input must fit into 168 bits
     */
    function toUint168(uint256 value) internal pure returns (uint168) {
        if (value > type(uint168).max) {
            revert SafeCastOverflowedUintDowncast(168, value);
        }
        return uint168(value);
    }

    /**
     * @dev Returns the downcasted uint160 from uint256, reverting on
     * overflow (when the input is greater than largest uint160).
     *
     * Counterpart to Solidity's `uint160` operator.
     *
     * Requirements:
     *
     * - input must fit into 160 bits
     */
    function toUint160(uint256 value) internal pure returns (uint160) {
        if (value > type(uint160).max) {
            revert SafeCastOverflowedUintDowncast(160, value);
        }
        return uint160(value);
    }

    /**
     * @dev Returns the downcasted uint152 from uint256, reverting on
     * overflow (when the input is greater than largest uint152).
     *
     * Counterpart to Solidity's `uint152` operator.
     *
     * Requirements:
     *
     * - input must fit into 152 bits
     */
    function toUint152(uint256 value) internal pure returns (uint152) {
        if (value > type(uint152).max) {
            revert SafeCastOverflowedUintDowncast(152, value);
        }
        return uint152(value);
    }

    /**
     * @dev Returns the downcasted uint144 from uint256, reverting on
     * overflow (when the input is greater than largest uint144).
     *
     * Counterpart to Solidity's `uint144` operator.
     *
     * Requirements:
     *
     * - input must fit into 144 bits
     */
    function toUint144(uint256 value) internal pure returns (uint144) {
        if (value > type(uint144).max) {
            revert SafeCastOverflowedUintDowncast(144, value);
        }
        return uint144(value);
    }

    /**
     * @dev Returns the downcasted uint136 from uint256, reverting on
     * overflow (when the input is greater than largest uint136).
     *
     * Counterpart to Solidity's `uint136` operator.
     *
     * Requirements:
     *
     * - input must fit into 136 bits
     */
    function toUint136(uint256 value) internal pure returns (uint136) {
        if (value > type(uint136).max) {
            revert SafeCastOverflowedUintDowncast(136, value);
        }
        return uint136(value);
    }

    /**
     * @dev Returns the downcasted uint128 from uint256, reverting on
     * overflow (when the input is greater than largest uint128).
     *
     * Counterpart to Solidity's `uint128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     */
    function toUint128(uint256 value) internal pure returns (uint128) {
        if (value > type(uint128).max) {
            revert SafeCastOverflowedUintDowncast(128, value);
        }
        return uint128(value);
    }

    /**
     * @dev Returns the downcasted uint120 from uint256, reverting on
     * overflow (when the input is greater than largest uint120).
     *
     * Counterpart to Solidity's `uint120` operator.
     *
     * Requirements:
     *
     * - input must fit into 120 bits
     */
    function toUint120(uint256 value) internal pure returns (uint120) {
        if (value > type(uint120).max) {
            revert SafeCastOverflowedUintDowncast(120, value);
        }
        return uint120(value);
    }

    /**
     * @dev Returns the downcasted uint112 from uint256, reverting on
     * overflow (when the input is greater than largest uint112).
     *
     * Counterpart to Solidity's `uint112` operator.
     *
     * Requirements:
     *
     * - input must fit into 112 bits
     */
    function toUint112(uint256 value) internal pure returns (uint112) {
        if (value > type(uint112).max) {
            revert SafeCastOverflowedUintDowncast(112, value);
        }
        return uint112(value);
    }

    /**
     * @dev Returns the downcasted uint104 from uint256, reverting on
     * overflow (when the input is greater than largest uint104).
     *
     * Counterpart to Solidity's `uint104` operator.
     *
     * Requirements:
     *
     * - input must fit into 104 bits
     */
    function toUint104(uint256 value) internal pure returns (uint104) {
        if (value > type(uint104).max) {
            revert SafeCastOverflowedUintDowncast(104, value);
        }
        return uint104(value);
    }

    /**
     * @dev Returns the downcasted uint96 from uint256, reverting on
     * overflow (when the input is greater than largest uint96).
     *
     * Counterpart to Solidity's `uint96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     */
    function toUint96(uint256 value) internal pure returns (uint96) {
        if (value > type(uint96).max) {
            revert SafeCastOverflowedUintDowncast(96, value);
        }
        return uint96(value);
    }

    /**
     * @dev Returns the downcasted uint88 from uint256, reverting on
     * overflow (when the input is greater than largest uint88).
     *
     * Counterpart to Solidity's `uint88` operator.
     *
     * Requirements:
     *
     * - input must fit into 88 bits
     */
    function toUint88(uint256 value) internal pure returns (uint88) {
        if (value > type(uint88).max) {
            revert SafeCastOverflowedUintDowncast(88, value);
        }
        return uint88(value);
    }

    /**
     * @dev Returns the downcasted uint80 from uint256, reverting on
     * overflow (when the input is greater than largest uint80).
     *
     * Counterpart to Solidity's `uint80` operator.
     *
     * Requirements:
     *
     * - input must fit into 80 bits
     */
    function toUint80(uint256 value) internal pure returns (uint80) {
        if (value > type(uint80).max) {
            revert SafeCastOverflowedUintDowncast(80, value);
        }
        return uint80(value);
    }

    /**
     * @dev Returns the downcasted uint72 from uint256, reverting on
     * overflow (when the input is greater than largest uint72).
     *
     * Counterpart to Solidity's `uint72` operator.
     *
     * Requirements:
     *
     * - input must fit into 72 bits
     */
    function toUint72(uint256 value) internal pure returns (uint72) {
        if (value > type(uint72).max) {
            revert SafeCastOverflowedUintDowncast(72, value);
        }
        return uint72(value);
    }

    /**
     * @dev Returns the downcasted uint64 from uint256, reverting on
     * overflow (when the input is greater than largest uint64).
     *
     * Counterpart to Solidity's `uint64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     */
    function toUint64(uint256 value) internal pure returns (uint64) {
        if (value > type(uint64).max) {
            revert SafeCastOverflowedUintDowncast(64, value);
        }
        return uint64(value);
    }

    /**
     * @dev Returns the downcasted uint56 from uint256, reverting on
     * overflow (when the input is greater than largest uint56).
     *
     * Counterpart to Solidity's `uint56` operator.
     *
     * Requirements:
     *
     * - input must fit into 56 bits
     */
    function toUint56(uint256 value) internal pure returns (uint56) {
        if (value > type(uint56).max) {
            revert SafeCastOverflowedUintDowncast(56, value);
        }
        return uint56(value);
    }

    /**
     * @dev Returns the downcasted uint48 from uint256, reverting on
     * overflow (when the input is greater than largest uint48).
     *
     * Counterpart to Solidity's `uint48` operator.
     *
     * Requirements:
     *
     * - input must fit into 48 bits
     */
    function toUint48(uint256 value) internal pure returns (uint48) {
        if (value > type(uint48).max) {
            revert SafeCastOverflowedUintDowncast(48, value);
        }
        return uint48(value);
    }

    /**
     * @dev Returns the downcasted uint40 from uint256, reverting on
     * overflow (when the input is greater than largest uint40).
     *
     * Counterpart to Solidity's `uint40` operator.
     *
     * Requirements:
     *
     * - input must fit into 40 bits
     */
    function toUint40(uint256 value) internal pure returns (uint40) {
        if (value > type(uint40).max) {
            revert SafeCastOverflowedUintDowncast(40, value);
        }
        return uint40(value);
    }

    /**
     * @dev Returns the downcasted uint32 from uint256, reverting on
     * overflow (when the input is greater than largest uint32).
     *
     * Counterpart to Solidity's `uint32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     */
    function toUint32(uint256 value) internal pure returns (uint32) {
        if (value > type(uint32).max) {
            revert SafeCastOverflowedUintDowncast(32, value);
        }
        return uint32(value);
    }

    /**
     * @dev Returns the downcasted uint24 from uint256, reverting on
     * overflow (when the input is greater than largest uint24).
     *
     * Counterpart to Solidity's `uint24` operator.
     *
     * Requirements:
     *
     * - input must fit into 24 bits
     */
    function toUint24(uint256 value) internal pure returns (uint24) {
        if (value > type(uint24).max) {
            revert SafeCastOverflowedUintDowncast(24, value);
        }
        return uint24(value);
    }

    /**
     * @dev Returns the downcasted uint16 from uint256, reverting on
     * overflow (when the input is greater than largest uint16).
     *
     * Counterpart to Solidity's `uint16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     */
    function toUint16(uint256 value) internal pure returns (uint16) {
        if (value > type(uint16).max) {
            revert SafeCastOverflowedUintDowncast(16, value);
        }
        return uint16(value);
    }

    /**
     * @dev Returns the downcasted uint8 from uint256, reverting on
     * overflow (when the input is greater than largest uint8).
     *
     * Counterpart to Solidity's `uint8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits
     */
    function toUint8(uint256 value) internal pure returns (uint8) {
        if (value > type(uint8).max) {
            revert SafeCastOverflowedUintDowncast(8, value);
        }
        return uint8(value);
    }

    /**
     * @dev Converts a signed int256 into an unsigned uint256.
     *
     * Requirements:
     *
     * - input must be greater than or equal to 0.
     */
    function toUint256(int256 value) internal pure returns (uint256) {
        if (value < 0) {
            revert SafeCastOverflowedIntToUint(value);
        }
        return uint256(value);
    }

    /**
     * @dev Returns the downcasted int248 from int256, reverting on
     * overflow (when the input is less than smallest int248 or
     * greater than largest int248).
     *
     * Counterpart to Solidity's `int248` operator.
     *
     * Requirements:
     *
     * - input must fit into 248 bits
     */
    function toInt248(int256 value) internal pure returns (int248 downcasted) {
        downcasted = int248(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(248, value);
        }
    }

    /**
     * @dev Returns the downcasted int240 from int256, reverting on
     * overflow (when the input is less than smallest int240 or
     * greater than largest int240).
     *
     * Counterpart to Solidity's `int240` operator.
     *
     * Requirements:
     *
     * - input must fit into 240 bits
     */
    function toInt240(int256 value) internal pure returns (int240 downcasted) {
        downcasted = int240(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(240, value);
        }
    }

    /**
     * @dev Returns the downcasted int232 from int256, reverting on
     * overflow (when the input is less than smallest int232 or
     * greater than largest int232).
     *
     * Counterpart to Solidity's `int232` operator.
     *
     * Requirements:
     *
     * - input must fit into 232 bits
     */
    function toInt232(int256 value) internal pure returns (int232 downcasted) {
        downcasted = int232(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(232, value);
        }
    }

    /**
     * @dev Returns the downcasted int224 from int256, reverting on
     * overflow (when the input is less than smallest int224 or
     * greater than largest int224).
     *
     * Counterpart to Solidity's `int224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     */
    function toInt224(int256 value) internal pure returns (int224 downcasted) {
        downcasted = int224(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(224, value);
        }
    }

    /**
     * @dev Returns the downcasted int216 from int256, reverting on
     * overflow (when the input is less than smallest int216 or
     * greater than largest int216).
     *
     * Counterpart to Solidity's `int216` operator.
     *
     * Requirements:
     *
     * - input must fit into 216 bits
     */
    function toInt216(int256 value) internal pure returns (int216 downcasted) {
        downcasted = int216(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(216, value);
        }
    }

    /**
     * @dev Returns the downcasted int208 from int256, reverting on
     * overflow (when the input is less than smallest int208 or
     * greater than largest int208).
     *
     * Counterpart to Solidity's `int208` operator.
     *
     * Requirements:
     *
     * - input must fit into 208 bits
     */
    function toInt208(int256 value) internal pure returns (int208 downcasted) {
        downcasted = int208(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(208, value);
        }
    }

    /**
     * @dev Returns the downcasted int200 from int256, reverting on
     * overflow (when the input is less than smallest int200 or
     * greater than largest int200).
     *
     * Counterpart to Solidity's `int200` operator.
     *
     * Requirements:
     *
     * - input must fit into 200 bits
     */
    function toInt200(int256 value) internal pure returns (int200 downcasted) {
        downcasted = int200(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(200, value);
        }
    }

    /**
     * @dev Returns the downcasted int192 from int256, reverting on
     * overflow (when the input is less than smallest int192 or
     * greater than largest int192).
     *
     * Counterpart to Solidity's `int192` operator.
     *
     * Requirements:
     *
     * - input must fit into 192 bits
     */
    function toInt192(int256 value) internal pure returns (int192 downcasted) {
        downcasted = int192(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(192, value);
        }
    }

    /**
     * @dev Returns the downcasted int184 from int256, reverting on
     * overflow (when the input is less than smallest int184 or
     * greater than largest int184).
     *
     * Counterpart to Solidity's `int184` operator.
     *
     * Requirements:
     *
     * - input must fit into 184 bits
     */
    function toInt184(int256 value) internal pure returns (int184 downcasted) {
        downcasted = int184(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(184, value);
        }
    }

    /**
     * @dev Returns the downcasted int176 from int256, reverting on
     * overflow (when the input is less than smallest int176 or
     * greater than largest int176).
     *
     * Counterpart to Solidity's `int176` operator.
     *
     * Requirements:
     *
     * - input must fit into 176 bits
     */
    function toInt176(int256 value) internal pure returns (int176 downcasted) {
        downcasted = int176(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(176, value);
        }
    }

    /**
     * @dev Returns the downcasted int168 from int256, reverting on
     * overflow (when the input is less than smallest int168 or
     * greater than largest int168).
     *
     * Counterpart to Solidity's `int168` operator.
     *
     * Requirements:
     *
     * - input must fit into 168 bits
     */
    function toInt168(int256 value) internal pure returns (int168 downcasted) {
        downcasted = int168(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(168, value);
        }
    }

    /**
     * @dev Returns the downcasted int160 from int256, reverting on
     * overflow (when the input is less than smallest int160 or
     * greater than largest int160).
     *
     * Counterpart to Solidity's `int160` operator.
     *
     * Requirements:
     *
     * - input must fit into 160 bits
     */
    function toInt160(int256 value) internal pure returns (int160 downcasted) {
        downcasted = int160(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(160, value);
        }
    }

    /**
     * @dev Returns the downcasted int152 from int256, reverting on
     * overflow (when the input is less than smallest int152 or
     * greater than largest int152).
     *
     * Counterpart to Solidity's `int152` operator.
     *
     * Requirements:
     *
     * - input must fit into 152 bits
     */
    function toInt152(int256 value) internal pure returns (int152 downcasted) {
        downcasted = int152(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(152, value);
        }
    }

    /**
     * @dev Returns the downcasted int144 from int256, reverting on
     * overflow (when the input is less than smallest int144 or
     * greater than largest int144).
     *
     * Counterpart to Solidity's `int144` operator.
     *
     * Requirements:
     *
     * - input must fit into 144 bits
     */
    function toInt144(int256 value) internal pure returns (int144 downcasted) {
        downcasted = int144(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(144, value);
        }
    }

    /**
     * @dev Returns the downcasted int136 from int256, reverting on
     * overflow (when the input is less than smallest int136 or
     * greater than largest int136).
     *
     * Counterpart to Solidity's `int136` operator.
     *
     * Requirements:
     *
     * - input must fit into 136 bits
     */
    function toInt136(int256 value) internal pure returns (int136 downcasted) {
        downcasted = int136(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(136, value);
        }
    }

    /**
     * @dev Returns the downcasted int128 from int256, reverting on
     * overflow (when the input is less than smallest int128 or
     * greater than largest int128).
     *
     * Counterpart to Solidity's `int128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     */
    function toInt128(int256 value) internal pure returns (int128 downcasted) {
        downcasted = int128(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(128, value);
        }
    }

    /**
     * @dev Returns the downcasted int120 from int256, reverting on
     * overflow (when the input is less than smallest int120 or
     * greater than largest int120).
     *
     * Counterpart to Solidity's `int120` operator.
     *
     * Requirements:
     *
     * - input must fit into 120 bits
     */
    function toInt120(int256 value) internal pure returns (int120 downcasted) {
        downcasted = int120(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(120, value);
        }
    }

    /**
     * @dev Returns the downcasted int112 from int256, reverting on
     * overflow (when the input is less than smallest int112 or
     * greater than largest int112).
     *
     * Counterpart to Solidity's `int112` operator.
     *
     * Requirements:
     *
     * - input must fit into 112 bits
     */
    function toInt112(int256 value) internal pure returns (int112 downcasted) {
        downcasted = int112(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(112, value);
        }
    }

    /**
     * @dev Returns the downcasted int104 from int256, reverting on
     * overflow (when the input is less than smallest int104 or
     * greater than largest int104).
     *
     * Counterpart to Solidity's `int104` operator.
     *
     * Requirements:
     *
     * - input must fit into 104 bits
     */
    function toInt104(int256 value) internal pure returns (int104 downcasted) {
        downcasted = int104(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(104, value);
        }
    }

    /**
     * @dev Returns the downcasted int96 from int256, reverting on
     * overflow (when the input is less than smallest int96 or
     * greater than largest int96).
     *
     * Counterpart to Solidity's `int96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     */
    function toInt96(int256 value) internal pure returns (int96 downcasted) {
        downcasted = int96(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(96, value);
        }
    }

    /**
     * @dev Returns the downcasted int88 from int256, reverting on
     * overflow (when the input is less than smallest int88 or
     * greater than largest int88).
     *
     * Counterpart to Solidity's `int88` operator.
     *
     * Requirements:
     *
     * - input must fit into 88 bits
     */
    function toInt88(int256 value) internal pure returns (int88 downcasted) {
        downcasted = int88(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(88, value);
        }
    }

    /**
     * @dev Returns the downcasted int80 from int256, reverting on
     * overflow (when the input is less than smallest int80 or
     * greater than largest int80).
     *
     * Counterpart to Solidity's `int80` operator.
     *
     * Requirements:
     *
     * - input must fit into 80 bits
     */
    function toInt80(int256 value) internal pure returns (int80 downcasted) {
        downcasted = int80(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(80, value);
        }
    }

    /**
     * @dev Returns the downcasted int72 from int256, reverting on
     * overflow (when the input is less than smallest int72 or
     * greater than largest int72).
     *
     * Counterpart to Solidity's `int72` operator.
     *
     * Requirements:
     *
     * - input must fit into 72 bits
     */
    function toInt72(int256 value) internal pure returns (int72 downcasted) {
        downcasted = int72(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(72, value);
        }
    }

    /**
     * @dev Returns the downcasted int64 from int256, reverting on
     * overflow (when the input is less than smallest int64 or
     * greater than largest int64).
     *
     * Counterpart to Solidity's `int64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     */
    function toInt64(int256 value) internal pure returns (int64 downcasted) {
        downcasted = int64(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(64, value);
        }
    }

    /**
     * @dev Returns the downcasted int56 from int256, reverting on
     * overflow (when the input is less than smallest int56 or
     * greater than largest int56).
     *
     * Counterpart to Solidity's `int56` operator.
     *
     * Requirements:
     *
     * - input must fit into 56 bits
     */
    function toInt56(int256 value) internal pure returns (int56 downcasted) {
        downcasted = int56(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(56, value);
        }
    }

    /**
     * @dev Returns the downcasted int48 from int256, reverting on
     * overflow (when the input is less than smallest int48 or
     * greater than largest int48).
     *
     * Counterpart to Solidity's `int48` operator.
     *
     * Requirements:
     *
     * - input must fit into 48 bits
     */
    function toInt48(int256 value) internal pure returns (int48 downcasted) {
        downcasted = int48(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(48, value);
        }
    }

    /**
     * @dev Returns the downcasted int40 from int256, reverting on
     * overflow (when the input is less than smallest int40 or
     * greater than largest int40).
     *
     * Counterpart to Solidity's `int40` operator.
     *
     * Requirements:
     *
     * - input must fit into 40 bits
     */
    function toInt40(int256 value) internal pure returns (int40 downcasted) {
        downcasted = int40(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(40, value);
        }
    }

    /**
     * @dev Returns the downcasted int32 from int256, reverting on
     * overflow (when the input is less than smallest int32 or
     * greater than largest int32).
     *
     * Counterpart to Solidity's `int32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     */
    function toInt32(int256 value) internal pure returns (int32 downcasted) {
        downcasted = int32(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(32, value);
        }
    }

    /**
     * @dev Returns the downcasted int24 from int256, reverting on
     * overflow (when the input is less than smallest int24 or
     * greater than largest int24).
     *
     * Counterpart to Solidity's `int24` operator.
     *
     * Requirements:
     *
     * - input must fit into 24 bits
     */
    function toInt24(int256 value) internal pure returns (int24 downcasted) {
        downcasted = int24(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(24, value);
        }
    }

    /**
     * @dev Returns the downcasted int16 from int256, reverting on
     * overflow (when the input is less than smallest int16 or
     * greater than largest int16).
     *
     * Counterpart to Solidity's `int16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     */
    function toInt16(int256 value) internal pure returns (int16 downcasted) {
        downcasted = int16(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(16, value);
        }
    }

    /**
     * @dev Returns the downcasted int8 from int256, reverting on
     * overflow (when the input is less than smallest int8 or
     * greater than largest int8).
     *
     * Counterpart to Solidity's `int8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits
     */
    function toInt8(int256 value) internal pure returns (int8 downcasted) {
        downcasted = int8(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(8, value);
        }
    }

    /**
     * @dev Converts an unsigned uint256 into a signed int256.
     *
     * Requirements:
     *
     * - input must be less than or equal to maxInt256.
     */
    function toInt256(uint256 value) internal pure returns (int256) {
        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
        if (value > uint256(type(int256).max)) {
            revert SafeCastOverflowedUintToInt(value);
        }
        return int256(value);
    }

    /**
     * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.
     */
    function toUint(bool b) internal pure returns (uint256 u) {
        assembly ("memory-safe") {
            u := iszero(iszero(b))
        }
    }
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;

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

interface IAccessControlFacet is IGenericMoreVaultFacetInitializable {
    error VaultHasNotAllowedFacet(address facet);
    error VaultHasNotAllowedSelector(address facet, bytes4 selector);
    error UnaibleToChangeRegistryToPermissionless();

    /**
     * @notice Transfers owner role to a new address
     * @param _newOwner Address of the new owner
     */
    function transferOwnership(address _newOwner) external;

    /**
     * @notice Accepts ownership role
     */
    function acceptOwnership() external;

    /**
     * @notice Transfers curator role to a new address
     * @param _newCurator Address of the new curator
     */
    function transferCuratorship(address _newCurator) external;

    /**
     * @notice Transfers guardian role to a new address
     * @param _newGuardian Address of the new guardian
     */
    function transferGuardian(address _newGuardian) external;

    /**
     * @notice Returns the current owner address
     * @return Address of the current owner
     */
    function owner() external view returns (address);

    /**
     * @notice Returns the current pending owner address
     * @return Address of the current pending owner
     */
    function pendingOwner() external view returns (address);

    /**
     * @notice Returns the current curator address
     * @return Address of the current curator
     */
    function curator() external view returns (address);

    /**
     * @notice Returns the current guardian address
     * @return Address of the current guardian
     */
    function guardian() external view returns (address);

    /**
     * @notice Returns the current more vault registry address
     * @return Address of the current more vault registry
     */
    function moreVaultsRegistry() external view returns (address);
}

File 29 of 41 : IConfigurationFacet.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;

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

interface IConfigurationFacet is IGenericMoreVaultFacetInitializable {
    /**
     * @dev Custom errors
     */
    error InvalidAddress();
    error InvalidPeriod();
    error AssetAlreadyAvailable();
    error AssetNotAvailable();
    error TimeLockPeriodNotExpired();
    error NothingSubmitted();
    error ArraysLengthsMismatch();
    error InvalidManager();
    error SlippageTooHigh();
    error FeeIsTooHigh();

    /**
     * @dev Events
     */
    /// @notice Emitted when the MoreVaults registry is set
    event MoreVaultRegistrySet(address indexed previousRegistry, address indexed newRegistry);
    /// @notice Emitted when a new asset is added
    event AssetAdded(address indexed asset);
    /// @notice Emitted when an asset is removed
    event AssetRemoved(address indexed asset);
    /// @notice Emitted when the withdrawal fee is set
    event WithdrawalFeeSet(uint96 fee);
    /// @notice Emitted when the withdrawal queue status is set
    event WithdrawalQueueStatusSet(bool status);
    /// @notice Emitted when the withdrawal timelock is set
    event WithdrawalTimelockSet(uint64 duration);
    /// @notice Emitted when the cross chain accounting manager is set
    event CrossChainAccountingManagerSet(address indexed manager);
    /// @notice Emitted when the max slippage percent is set
    event MaxSlippagePercentSet(uint256 percent);

    /**
     * @notice Sets fee recipient address, callable by owner
     * @param recipient New fee recipient address
     */
    function setFeeRecipient(address recipient) external;

    /**
     * @notice Sets time lock period, callable by owner through `submitActions` and timelocked
     * @param period New time lock period (in seconds)
     */
    function setTimeLockPeriod(uint256 period) external;

    /**
     * @notice Sets deposit capacity, callable by curator or owner
     * @param capacity New deposit capacity
     */
    function setDepositCapacity(uint256 capacity) external;

    /**
     * @notice Sets deposit whitelist, callable by owner
     * @param depositors Array of depositors
     * @param undelyingAssetCaps Array of underlying asset caps
     */
    function setDepositWhitelist(address[] calldata depositors, uint256[] calldata undelyingAssetCaps) external;

    /**
     * @notice Enables deposit whitelist, callable by owner
     */
    function enableDepositWhitelist() external;

    /**
     * @notice Disables deposit whitelist, callable by owner through `submitActions` and timelocked
     */
    function disableDepositWhitelist() external;

    /**
     * @notice Disables deposit whitelist
     */
    /**
     * @notice Gets deposit whitelist
     * @param depositor Depositor address
     * @return Undelying asset cap
     */
    function getDepositWhitelist(address depositor) external view returns (uint256);

    /**
     * @notice Adds new available asset, callable by curator or owner
     * @param asset Asset address to add
     */
    function addAvailableAsset(address asset) external;

    /**
     * @notice Batch adds new available assets, callable by curator or owner
     * @param assets Array of asset addresses to add
     */
    function addAvailableAssets(address[] calldata assets) external;

    /**
     * @notice Enables asset to deposit, callable by curator or owner through `submitActions` and timelocked
     * @param asset Asset address to enable
     */
    function enableAssetToDeposit(address asset) external;

    /**
     * @notice Disables asset to deposit, callable by curator
     * @param asset Asset address to disable
     */
    function disableAssetToDeposit(address asset) external;

    /**
     * @notice Set the withdrawal fee, callable by owner through `submitActions` and timelocked
     * @param _fee New withdrawal fee
     */
    function setWithdrawalFee(uint96 _fee) external;

    /**
     * @notice Update the withdraw timelock duration, callable by owner through `submitActions` and timelocked
     * @param duration New withdraw timelock duration
     */
    function setWithdrawalTimelock(uint64 duration) external;

    /**
     * @notice Update the withdrawal queue status, callable by owner through `submitActions` and timelocked
     * @param _status New withdrawal queue status
     */
    function updateWithdrawalQueueStatus(bool _status) external;

    /**
     * @notice Sets gas limit for accounting, callable by curator or owner through `submitActions` and timelocked
     * @param _availableTokenAccountingGas Gas limit for available token accounting
     * @param _heldTokenAccountingGas Gas limit for held token accounting
     * @param _facetAccountingGas Gas limit for facet accounting
     * @param _newLimit New gas limit
     */
    function setGasLimitForAccounting(
        uint48 _availableTokenAccountingGas,
        uint48 _heldTokenAccountingGas,
        uint48 _facetAccountingGas,
        uint48 _newLimit
    ) external;

    /**
     * @notice Sets max slippage percent, callable by curator or owner through `submitActions` and timelocked
     * @param _newPercent New max slippage percent
     */
    function setMaxSlippagePercent(uint256 _newPercent) external;

    /**
     * @notice Sets cross chain accounting manager, callable by owner through `submitActions` and timelocked
     * @param manager New cross chain accounting manager
     */
    function setCrossChainAccountingManager(address manager) external;

    /**
     * @notice Get the current withdrawal fee
     * @return The current withdrawal fee in basis points
     */
    function getWithdrawalFee() external view returns (uint96);

    /**
     * @notice Get the current withdrawal queue status
     * @return The current withdrawal queue status
     */
    function getWithdrawalQueueStatus() external view returns (bool);

    /**
     * @notice Gets list of depositable assets
     * @return Array of depositable asset addresses
     */
    function getDepositableAssets() external view returns (address[] memory);

    /**
     * @notice Checks if asset is available
     * @param asset Asset address to check
     * @return true if asset is available
     */
    function isAssetAvailable(address asset) external view returns (bool);

    /**
     * @notice Checks if asset is depositable
     * @param asset Asset address to check
     * @return true if asset is depositable
     */
    function isAssetDepositable(address asset) external view returns (bool);

    /**
     * @notice Checks if deposit whitelist is enabled
     * @return true if deposit whitelist is enabled
     */
    function isDepositWhitelistEnabled() external view returns (bool);

    /**
     * @notice Checks if vault is hub
     * @return true if vault is hub
     */
    function isHub() external view returns (bool);

    /**
     * @notice Gets list of all available assets
     * @return Array of available asset addresses
     */
    function getAvailableAssets() external view returns (address[] memory);

    /**
     * @notice Gets fee amount
     * @return Fee amount
     */
    function fee() external view returns (uint96);

    /**
     * @notice Gets fee recipient address
     * @return Fee recipient address
     */
    function feeRecipient() external view returns (address);

    /**
     * @notice Gets deposit capacity
     * @return Deposit capacity
     */
    function depositCapacity() external view returns (uint256);

    /**
     * @notice Gets time lock period
     * @return Time lock period
     */
    function timeLockPeriod() external view returns (uint256);

    /// @notice Returns the withdrawal timelock duration
    /// @return duration The withdrawal timelock duration
    function getWithdrawalTimelock() external view returns (uint64);

    /// @notice Get the lockedTokens amount of an asset
    /// @param asset The asset to get the lockedTokens amount of
    /// @return The lockedTokens amount of the asset
    function lockedTokensAmountOfAsset(address asset) external view returns (uint256);

    /// @notice Get the staking addresses for a given staking facet
    /// @param stakingFacetId The staking facet to get the staking addresses of
    /// @return The staking addresses for the given staking facet
    function getStakingAddresses(bytes32 stakingFacetId) external view returns (address[] memory);

    /// @notice Returns array of tokens held in the vault based on their IDs
    /// @param tokenId token type ID
    /// @return array of token addresses
    function tokensHeld(bytes32 tokenId) external view returns (address[] memory);

    /// @notice Get the cross chain accounting manager
    /// @return The cross chain accounting manager
    function getCrossChainAccountingManager() external view returns (address);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1363.sol)

pragma solidity >=0.6.2;

import {IERC20} from "./IERC20.sol";
import {IERC165} from "./IERC165.sol";

/**
 * @title IERC1363
 * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].
 *
 * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract
 * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.
 */
interface IERC1363 is IERC20, IERC165 {
    /*
     * Note: the ERC-165 identifier for this interface is 0xb0202a11.
     * 0xb0202a11 ===
     *   bytes4(keccak256('transferAndCall(address,uint256)')) ^
     *   bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
     *   bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
     *   bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
     *   bytes4(keccak256('approveAndCall(address,uint256)')) ^
     *   bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
     */

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferAndCall(address to, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @param data Additional data with no specified format, sent in call to `to`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param from The address which you want to send tokens from.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferFromAndCall(address from, address to, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param from The address which you want to send tokens from.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @param data Additional data with no specified format, sent in call to `to`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
     * @param spender The address which will spend the funds.
     * @param value The amount of tokens to be spent.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function approveAndCall(address spender, uint256 value) external returns (bool);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
     * @param spender The address which will spend the funds.
     * @param value The amount of tokens to be spent.
     * @param data Additional data with no specified format, sent in call to `spender`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.

pragma solidity ^0.8.20;

/**
 * @dev Library for reading and writing primitive types to specific storage slots.
 *
 * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
 * This library helps with reading and writing to such slots without the need for inline assembly.
 *
 * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
 *
 * Example usage to set ERC-1967 implementation slot:
 * ```solidity
 * contract ERC1967 {
 *     // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.
 *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
 *
 *     function _getImplementation() internal view returns (address) {
 *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
 *     }
 *
 *     function _setImplementation(address newImplementation) internal {
 *         require(newImplementation.code.length > 0);
 *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
 *     }
 * }
 * ```
 *
 * TIP: Consider using this library along with {SlotDerivation}.
 */
library StorageSlot {
    struct AddressSlot {
        address value;
    }

    struct BooleanSlot {
        bool value;
    }

    struct Bytes32Slot {
        bytes32 value;
    }

    struct Uint256Slot {
        uint256 value;
    }

    struct Int256Slot {
        int256 value;
    }

    struct StringSlot {
        string value;
    }

    struct BytesSlot {
        bytes value;
    }

    /**
     * @dev Returns an `AddressSlot` with member `value` located at `slot`.
     */
    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    /**
     * @dev Returns a `BooleanSlot` with member `value` located at `slot`.
     */
    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    /**
     * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.
     */
    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    /**
     * @dev Returns a `Uint256Slot` with member `value` located at `slot`.
     */
    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    /**
     * @dev Returns a `Int256Slot` with member `value` located at `slot`.
     */
    function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    /**
     * @dev Returns a `StringSlot` with member `value` located at `slot`.
     */
    function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `StringSlot` representation of the string storage pointer `store`.
     */
    function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
        assembly ("memory-safe") {
            r.slot := store.slot
        }
    }

    /**
     * @dev Returns a `BytesSlot` with member `value` located at `slot`.
     */
    function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
     */
    function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
        assembly ("memory-safe") {
            r.slot := store.slot
        }
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0;

struct SetConfigParam {
    uint32 eid;
    uint32 configType;
    bytes config;
}

interface IMessageLibManager {
    struct Timeout {
        address lib;
        uint256 expiry;
    }

    event LibraryRegistered(address newLib);
    event DefaultSendLibrarySet(uint32 eid, address newLib);
    event DefaultReceiveLibrarySet(uint32 eid, address newLib);
    event DefaultReceiveLibraryTimeoutSet(uint32 eid, address oldLib, uint256 expiry);
    event SendLibrarySet(address sender, uint32 eid, address newLib);
    event ReceiveLibrarySet(address receiver, uint32 eid, address newLib);
    event ReceiveLibraryTimeoutSet(address receiver, uint32 eid, address oldLib, uint256 timeout);

    function registerLibrary(address _lib) external;

    function isRegisteredLibrary(address _lib) external view returns (bool);

    function getRegisteredLibraries() external view returns (address[] memory);

    function setDefaultSendLibrary(uint32 _eid, address _newLib) external;

    function defaultSendLibrary(uint32 _eid) external view returns (address);

    function setDefaultReceiveLibrary(uint32 _eid, address _newLib, uint256 _timeout) external;

    function defaultReceiveLibrary(uint32 _eid) external view returns (address);

    function setDefaultReceiveLibraryTimeout(uint32 _eid, address _lib, uint256 _expiry) external;

    function defaultReceiveLibraryTimeout(uint32 _eid) external view returns (address lib, uint256 expiry);

    function isSupportedEid(uint32 _eid) external view returns (bool);

    function isValidReceiveLibrary(address _receiver, uint32 _eid, address _lib) external view returns (bool);

    /// ------------------- OApp interfaces -------------------
    function setSendLibrary(address _oapp, uint32 _eid, address _newLib) external;

    function getSendLibrary(address _sender, uint32 _eid) external view returns (address lib);

    function isDefaultSendLibrary(address _sender, uint32 _eid) external view returns (bool);

    function setReceiveLibrary(address _oapp, uint32 _eid, address _newLib, uint256 _gracePeriod) external;

    function getReceiveLibrary(address _receiver, uint32 _eid) external view returns (address lib, bool isDefault);

    function setReceiveLibraryTimeout(address _oapp, uint32 _eid, address _lib, uint256 _gracePeriod) external;

    function receiveLibraryTimeout(address _receiver, uint32 _eid) external view returns (address lib, uint256 expiry);

    function setConfig(address _oapp, address _lib, SetConfigParam[] calldata _params) external;

    function getConfig(
        address _oapp,
        address _lib,
        uint32 _eid,
        uint32 _configType
    ) external view returns (bytes memory config);
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0;

interface IMessagingComposer {
    event ComposeSent(address from, address to, bytes32 guid, uint16 index, bytes message);
    event ComposeDelivered(address from, address to, bytes32 guid, uint16 index);
    event LzComposeAlert(
        address indexed from,
        address indexed to,
        address indexed executor,
        bytes32 guid,
        uint16 index,
        uint256 gas,
        uint256 value,
        bytes message,
        bytes extraData,
        bytes reason
    );

    function composeQueue(
        address _from,
        address _to,
        bytes32 _guid,
        uint16 _index
    ) external view returns (bytes32 messageHash);

    function sendCompose(address _to, bytes32 _guid, uint16 _index, bytes calldata _message) external;

    function lzCompose(
        address _from,
        address _to,
        bytes32 _guid,
        uint16 _index,
        bytes calldata _message,
        bytes calldata _extraData
    ) external payable;
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0;

interface IMessagingChannel {
    event InboundNonceSkipped(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce);
    event PacketNilified(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce, bytes32 payloadHash);
    event PacketBurnt(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce, bytes32 payloadHash);

    function eid() external view returns (uint32);

    // this is an emergency function if a message cannot be verified for some reasons
    // required to provide _nextNonce to avoid race condition
    function skip(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce) external;

    function nilify(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce, bytes32 _payloadHash) external;

    function burn(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce, bytes32 _payloadHash) external;

    function nextGuid(address _sender, uint32 _dstEid, bytes32 _receiver) external view returns (bytes32);

    function inboundNonce(address _receiver, uint32 _srcEid, bytes32 _sender) external view returns (uint64);

    function outboundNonce(address _sender, uint32 _dstEid, bytes32 _receiver) external view returns (uint64);

    function inboundPayloadHash(
        address _receiver,
        uint32 _srcEid,
        bytes32 _sender,
        uint64 _nonce
    ) external view returns (bytes32);

    function lazyInboundNonce(address _receiver, uint32 _srcEid, bytes32 _sender) external view returns (uint64);
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0;

interface IMessagingContext {
    function isSendingMessage() external view returns (bool);

    function getSendContext() external view returns (uint32 dstEid, address sender);
}

File 36 of 41 : Arrays.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (utils/Arrays.sol)
// This file was procedurally generated from scripts/generate/templates/Arrays.js.

pragma solidity ^0.8.20;

import {Comparators} from "./Comparators.sol";
import {SlotDerivation} from "./SlotDerivation.sol";
import {StorageSlot} from "./StorageSlot.sol";
import {Math} from "./math/Math.sol";

/**
 * @dev Collection of functions related to array types.
 */
library Arrays {
    using SlotDerivation for bytes32;
    using StorageSlot for bytes32;

    /**
     * @dev Sort an array of uint256 (in memory) following the provided comparator function.
     *
     * This function does the sorting "in place", meaning that it overrides the input. The object is returned for
     * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.
     *
     * NOTE: this function's cost is `O(n · log(n))` in average and `O(n²)` in the worst case, with n the length of the
     * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful
     * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may
     * consume more gas than is available in a block, leading to potential DoS.
     *
     * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.
     */
    function sort(
        uint256[] memory array,
        function(uint256, uint256) pure returns (bool) comp
    ) internal pure returns (uint256[] memory) {
        _quickSort(_begin(array), _end(array), comp);
        return array;
    }

    /**
     * @dev Variant of {sort} that sorts an array of uint256 in increasing order.
     */
    function sort(uint256[] memory array) internal pure returns (uint256[] memory) {
        sort(array, Comparators.lt);
        return array;
    }

    /**
     * @dev Sort an array of address (in memory) following the provided comparator function.
     *
     * This function does the sorting "in place", meaning that it overrides the input. The object is returned for
     * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.
     *
     * NOTE: this function's cost is `O(n · log(n))` in average and `O(n²)` in the worst case, with n the length of the
     * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful
     * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may
     * consume more gas than is available in a block, leading to potential DoS.
     *
     * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.
     */
    function sort(
        address[] memory array,
        function(address, address) pure returns (bool) comp
    ) internal pure returns (address[] memory) {
        sort(_castToUint256Array(array), _castToUint256Comp(comp));
        return array;
    }

    /**
     * @dev Variant of {sort} that sorts an array of address in increasing order.
     */
    function sort(address[] memory array) internal pure returns (address[] memory) {
        sort(_castToUint256Array(array), Comparators.lt);
        return array;
    }

    /**
     * @dev Sort an array of bytes32 (in memory) following the provided comparator function.
     *
     * This function does the sorting "in place", meaning that it overrides the input. The object is returned for
     * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.
     *
     * NOTE: this function's cost is `O(n · log(n))` in average and `O(n²)` in the worst case, with n the length of the
     * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful
     * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may
     * consume more gas than is available in a block, leading to potential DoS.
     *
     * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.
     */
    function sort(
        bytes32[] memory array,
        function(bytes32, bytes32) pure returns (bool) comp
    ) internal pure returns (bytes32[] memory) {
        sort(_castToUint256Array(array), _castToUint256Comp(comp));
        return array;
    }

    /**
     * @dev Variant of {sort} that sorts an array of bytes32 in increasing order.
     */
    function sort(bytes32[] memory array) internal pure returns (bytes32[] memory) {
        sort(_castToUint256Array(array), Comparators.lt);
        return array;
    }

    /**
     * @dev Performs a quick sort of a segment of memory. The segment sorted starts at `begin` (inclusive), and stops
     * at end (exclusive). Sorting follows the `comp` comparator.
     *
     * Invariant: `begin <= end`. This is the case when initially called by {sort} and is preserved in subcalls.
     *
     * IMPORTANT: Memory locations between `begin` and `end` are not validated/zeroed. This function should
     * be used only if the limits are within a memory array.
     */
    function _quickSort(uint256 begin, uint256 end, function(uint256, uint256) pure returns (bool) comp) private pure {
        unchecked {
            if (end - begin < 0x40) return;

            // Use first element as pivot
            uint256 pivot = _mload(begin);
            // Position where the pivot should be at the end of the loop
            uint256 pos = begin;

            for (uint256 it = begin + 0x20; it < end; it += 0x20) {
                if (comp(_mload(it), pivot)) {
                    // If the value stored at the iterator's position comes before the pivot, we increment the
                    // position of the pivot and move the value there.
                    pos += 0x20;
                    _swap(pos, it);
                }
            }

            _swap(begin, pos); // Swap pivot into place
            _quickSort(begin, pos, comp); // Sort the left side of the pivot
            _quickSort(pos + 0x20, end, comp); // Sort the right side of the pivot
        }
    }

    /**
     * @dev Pointer to the memory location of the first element of `array`.
     */
    function _begin(uint256[] memory array) private pure returns (uint256 ptr) {
        assembly ("memory-safe") {
            ptr := add(array, 0x20)
        }
    }

    /**
     * @dev Pointer to the memory location of the first memory word (32bytes) after `array`. This is the memory word
     * that comes just after the last element of the array.
     */
    function _end(uint256[] memory array) private pure returns (uint256 ptr) {
        unchecked {
            return _begin(array) + array.length * 0x20;
        }
    }

    /**
     * @dev Load memory word (as a uint256) at location `ptr`.
     */
    function _mload(uint256 ptr) private pure returns (uint256 value) {
        assembly {
            value := mload(ptr)
        }
    }

    /**
     * @dev Swaps the elements memory location `ptr1` and `ptr2`.
     */
    function _swap(uint256 ptr1, uint256 ptr2) private pure {
        assembly {
            let value1 := mload(ptr1)
            let value2 := mload(ptr2)
            mstore(ptr1, value2)
            mstore(ptr2, value1)
        }
    }

    /// @dev Helper: low level cast address memory array to uint256 memory array
    function _castToUint256Array(address[] memory input) private pure returns (uint256[] memory output) {
        assembly {
            output := input
        }
    }

    /// @dev Helper: low level cast bytes32 memory array to uint256 memory array
    function _castToUint256Array(bytes32[] memory input) private pure returns (uint256[] memory output) {
        assembly {
            output := input
        }
    }

    /// @dev Helper: low level cast address comp function to uint256 comp function
    function _castToUint256Comp(
        function(address, address) pure returns (bool) input
    ) private pure returns (function(uint256, uint256) pure returns (bool) output) {
        assembly {
            output := input
        }
    }

    /// @dev Helper: low level cast bytes32 comp function to uint256 comp function
    function _castToUint256Comp(
        function(bytes32, bytes32) pure returns (bool) input
    ) private pure returns (function(uint256, uint256) pure returns (bool) output) {
        assembly {
            output := input
        }
    }

    /**
     * @dev Searches a sorted `array` and returns the first index that contains
     * a value greater or equal to `element`. If no such index exists (i.e. all
     * values in the array are strictly less than `element`), the array length is
     * returned. Time complexity O(log n).
     *
     * NOTE: The `array` is expected to be sorted in ascending order, and to
     * contain no repeated elements.
     *
     * IMPORTANT: Deprecated. This implementation behaves as {lowerBound} but lacks
     * support for repeated elements in the array. The {lowerBound} function should
     * be used instead.
     */
    function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {
        uint256 low = 0;
        uint256 high = array.length;

        if (high == 0) {
            return 0;
        }

        while (low < high) {
            uint256 mid = Math.average(low, high);

            // Note that mid will always be strictly less than high (i.e. it will be a valid array index)
            // because Math.average rounds towards zero (it does integer division with truncation).
            if (unsafeAccess(array, mid).value > element) {
                high = mid;
            } else {
                low = mid + 1;
            }
        }

        // At this point `low` is the exclusive upper bound. We will return the inclusive upper bound.
        if (low > 0 && unsafeAccess(array, low - 1).value == element) {
            return low - 1;
        } else {
            return low;
        }
    }

    /**
     * @dev Searches an `array` sorted in ascending order and returns the first
     * index that contains a value greater or equal than `element`. If no such index
     * exists (i.e. all values in the array are strictly less than `element`), the array
     * length is returned. Time complexity O(log n).
     *
     * See C++'s https://en.cppreference.com/w/cpp/algorithm/lower_bound[lower_bound].
     */
    function lowerBound(uint256[] storage array, uint256 element) internal view returns (uint256) {
        uint256 low = 0;
        uint256 high = array.length;

        if (high == 0) {
            return 0;
        }

        while (low < high) {
            uint256 mid = Math.average(low, high);

            // Note that mid will always be strictly less than high (i.e. it will be a valid array index)
            // because Math.average rounds towards zero (it does integer division with truncation).
            if (unsafeAccess(array, mid).value < element) {
                // this cannot overflow because mid < high
                unchecked {
                    low = mid + 1;
                }
            } else {
                high = mid;
            }
        }

        return low;
    }

    /**
     * @dev Searches an `array` sorted in ascending order and returns the first
     * index that contains a value strictly greater than `element`. If no such index
     * exists (i.e. all values in the array are strictly less than `element`), the array
     * length is returned. Time complexity O(log n).
     *
     * See C++'s https://en.cppreference.com/w/cpp/algorithm/upper_bound[upper_bound].
     */
    function upperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {
        uint256 low = 0;
        uint256 high = array.length;

        if (high == 0) {
            return 0;
        }

        while (low < high) {
            uint256 mid = Math.average(low, high);

            // Note that mid will always be strictly less than high (i.e. it will be a valid array index)
            // because Math.average rounds towards zero (it does integer division with truncation).
            if (unsafeAccess(array, mid).value > element) {
                high = mid;
            } else {
                // this cannot overflow because mid < high
                unchecked {
                    low = mid + 1;
                }
            }
        }

        return low;
    }

    /**
     * @dev Same as {lowerBound}, but with an array in memory.
     */
    function lowerBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) {
        uint256 low = 0;
        uint256 high = array.length;

        if (high == 0) {
            return 0;
        }

        while (low < high) {
            uint256 mid = Math.average(low, high);

            // Note that mid will always be strictly less than high (i.e. it will be a valid array index)
            // because Math.average rounds towards zero (it does integer division with truncation).
            if (unsafeMemoryAccess(array, mid) < element) {
                // this cannot overflow because mid < high
                unchecked {
                    low = mid + 1;
                }
            } else {
                high = mid;
            }
        }

        return low;
    }

    /**
     * @dev Same as {upperBound}, but with an array in memory.
     */
    function upperBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) {
        uint256 low = 0;
        uint256 high = array.length;

        if (high == 0) {
            return 0;
        }

        while (low < high) {
            uint256 mid = Math.average(low, high);

            // Note that mid will always be strictly less than high (i.e. it will be a valid array index)
            // because Math.average rounds towards zero (it does integer division with truncation).
            if (unsafeMemoryAccess(array, mid) > element) {
                high = mid;
            } else {
                // this cannot overflow because mid < high
                unchecked {
                    low = mid + 1;
                }
            }
        }

        return low;
    }

    /**
     * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
     *
     * WARNING: Only use if you are certain `pos` is lower than the array length.
     */
    function unsafeAccess(address[] storage arr, uint256 pos) internal pure returns (StorageSlot.AddressSlot storage) {
        bytes32 slot;
        assembly ("memory-safe") {
            slot := arr.slot
        }
        return slot.deriveArray().offset(pos).getAddressSlot();
    }

    /**
     * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
     *
     * WARNING: Only use if you are certain `pos` is lower than the array length.
     */
    function unsafeAccess(bytes32[] storage arr, uint256 pos) internal pure returns (StorageSlot.Bytes32Slot storage) {
        bytes32 slot;
        assembly ("memory-safe") {
            slot := arr.slot
        }
        return slot.deriveArray().offset(pos).getBytes32Slot();
    }

    /**
     * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
     *
     * WARNING: Only use if you are certain `pos` is lower than the array length.
     */
    function unsafeAccess(uint256[] storage arr, uint256 pos) internal pure returns (StorageSlot.Uint256Slot storage) {
        bytes32 slot;
        assembly ("memory-safe") {
            slot := arr.slot
        }
        return slot.deriveArray().offset(pos).getUint256Slot();
    }

    /**
     * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
     *
     * WARNING: Only use if you are certain `pos` is lower than the array length.
     */
    function unsafeAccess(bytes[] storage arr, uint256 pos) internal pure returns (StorageSlot.BytesSlot storage) {
        bytes32 slot;
        assembly ("memory-safe") {
            slot := arr.slot
        }
        return slot.deriveArray().offset(pos).getBytesSlot();
    }

    /**
     * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
     *
     * WARNING: Only use if you are certain `pos` is lower than the array length.
     */
    function unsafeAccess(string[] storage arr, uint256 pos) internal pure returns (StorageSlot.StringSlot storage) {
        bytes32 slot;
        assembly ("memory-safe") {
            slot := arr.slot
        }
        return slot.deriveArray().offset(pos).getStringSlot();
    }

    /**
     * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
     *
     * WARNING: Only use if you are certain `pos` is lower than the array length.
     */
    function unsafeMemoryAccess(address[] memory arr, uint256 pos) internal pure returns (address res) {
        assembly {
            res := mload(add(add(arr, 0x20), mul(pos, 0x20)))
        }
    }

    /**
     * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
     *
     * WARNING: Only use if you are certain `pos` is lower than the array length.
     */
    function unsafeMemoryAccess(bytes32[] memory arr, uint256 pos) internal pure returns (bytes32 res) {
        assembly {
            res := mload(add(add(arr, 0x20), mul(pos, 0x20)))
        }
    }

    /**
     * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
     *
     * WARNING: Only use if you are certain `pos` is lower than the array length.
     */
    function unsafeMemoryAccess(uint256[] memory arr, uint256 pos) internal pure returns (uint256 res) {
        assembly {
            res := mload(add(add(arr, 0x20), mul(pos, 0x20)))
        }
    }

    /**
     * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
     *
     * WARNING: Only use if you are certain `pos` is lower than the array length.
     */
    function unsafeMemoryAccess(bytes[] memory arr, uint256 pos) internal pure returns (bytes memory res) {
        assembly {
            res := mload(add(add(arr, 0x20), mul(pos, 0x20)))
        }
    }

    /**
     * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
     *
     * WARNING: Only use if you are certain `pos` is lower than the array length.
     */
    function unsafeMemoryAccess(string[] memory arr, uint256 pos) internal pure returns (string memory res) {
        assembly {
            res := mload(add(add(arr, 0x20), mul(pos, 0x20)))
        }
    }

    /**
     * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.
     *
     * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.
     */
    function unsafeSetLength(address[] storage array, uint256 len) internal {
        assembly ("memory-safe") {
            sstore(array.slot, len)
        }
    }

    /**
     * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.
     *
     * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.
     */
    function unsafeSetLength(bytes32[] storage array, uint256 len) internal {
        assembly ("memory-safe") {
            sstore(array.slot, len)
        }
    }

    /**
     * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.
     *
     * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.
     */
    function unsafeSetLength(uint256[] storage array, uint256 len) internal {
        assembly ("memory-safe") {
            sstore(array.slot, len)
        }
    }

    /**
     * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.
     *
     * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.
     */
    function unsafeSetLength(bytes[] storage array, uint256 len) internal {
        assembly ("memory-safe") {
            sstore(array.slot, len)
        }
    }

    /**
     * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.
     *
     * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.
     */
    function unsafeSetLength(string[] storage array, uint256 len) internal {
        assembly ("memory-safe") {
            sstore(array.slot, len)
        }
    }
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;

interface IGenericMoreVaultFacet {
    function facetName() external view returns (string memory);

    function facetVersion() external view returns (string memory);
}

File 38 of 41 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC165.sol)

pragma solidity >=0.4.16;

import {IERC165} from "../utils/introspection/IERC165.sol";

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Comparators.sol)

pragma solidity ^0.8.20;

/**
 * @dev Provides a set of functions to compare values.
 *
 * _Available since v5.1._
 */
library Comparators {
    function lt(uint256 a, uint256 b) internal pure returns (bool) {
        return a < b;
    }

    function gt(uint256 a, uint256 b) internal pure returns (bool) {
        return a > b;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (utils/SlotDerivation.sol)
// This file was procedurally generated from scripts/generate/templates/SlotDerivation.js.

pragma solidity ^0.8.20;

/**
 * @dev Library for computing storage (and transient storage) locations from namespaces and deriving slots
 * corresponding to standard patterns. The derivation method for array and mapping matches the storage layout used by
 * the solidity language / compiler.
 *
 * See https://docs.soliditylang.org/en/v0.8.20/internals/layout_in_storage.html#mappings-and-dynamic-arrays[Solidity docs for mappings and dynamic arrays.].
 *
 * Example usage:
 * ```solidity
 * contract Example {
 *     // Add the library methods
 *     using StorageSlot for bytes32;
 *     using SlotDerivation for bytes32;
 *
 *     // Declare a namespace
 *     string private constant _NAMESPACE = "<namespace>"; // eg. OpenZeppelin.Slot
 *
 *     function setValueInNamespace(uint256 key, address newValue) internal {
 *         _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value = newValue;
 *     }
 *
 *     function getValueInNamespace(uint256 key) internal view returns (address) {
 *         return _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value;
 *     }
 * }
 * ```
 *
 * TIP: Consider using this library along with {StorageSlot}.
 *
 * NOTE: This library provides a way to manipulate storage locations in a non-standard way. Tooling for checking
 * upgrade safety will ignore the slots accessed through this library.
 *
 * _Available since v5.1._
 */
library SlotDerivation {
    /**
     * @dev Derive an ERC-7201 slot from a string (namespace).
     */
    function erc7201Slot(string memory namespace) internal pure returns (bytes32 slot) {
        assembly ("memory-safe") {
            mstore(0x00, sub(keccak256(add(namespace, 0x20), mload(namespace)), 1))
            slot := and(keccak256(0x00, 0x20), not(0xff))
        }
    }

    /**
     * @dev Add an offset to a slot to get the n-th element of a structure or an array.
     */
    function offset(bytes32 slot, uint256 pos) internal pure returns (bytes32 result) {
        unchecked {
            return bytes32(uint256(slot) + pos);
        }
    }

    /**
     * @dev Derive the location of the first element in an array from the slot where the length is stored.
     */
    function deriveArray(bytes32 slot) internal pure returns (bytes32 result) {
        assembly ("memory-safe") {
            mstore(0x00, slot)
            result := keccak256(0x00, 0x20)
        }
    }

    /**
     * @dev Derive the location of a mapping element from the key.
     */
    function deriveMapping(bytes32 slot, address key) internal pure returns (bytes32 result) {
        assembly ("memory-safe") {
            mstore(0x00, and(key, shr(96, not(0))))
            mstore(0x20, slot)
            result := keccak256(0x00, 0x40)
        }
    }

    /**
     * @dev Derive the location of a mapping element from the key.
     */
    function deriveMapping(bytes32 slot, bool key) internal pure returns (bytes32 result) {
        assembly ("memory-safe") {
            mstore(0x00, iszero(iszero(key)))
            mstore(0x20, slot)
            result := keccak256(0x00, 0x40)
        }
    }

    /**
     * @dev Derive the location of a mapping element from the key.
     */
    function deriveMapping(bytes32 slot, bytes32 key) internal pure returns (bytes32 result) {
        assembly ("memory-safe") {
            mstore(0x00, key)
            mstore(0x20, slot)
            result := keccak256(0x00, 0x40)
        }
    }

    /**
     * @dev Derive the location of a mapping element from the key.
     */
    function deriveMapping(bytes32 slot, uint256 key) internal pure returns (bytes32 result) {
        assembly ("memory-safe") {
            mstore(0x00, key)
            mstore(0x20, slot)
            result := keccak256(0x00, 0x40)
        }
    }

    /**
     * @dev Derive the location of a mapping element from the key.
     */
    function deriveMapping(bytes32 slot, int256 key) internal pure returns (bytes32 result) {
        assembly ("memory-safe") {
            mstore(0x00, key)
            mstore(0x20, slot)
            result := keccak256(0x00, 0x40)
        }
    }

    /**
     * @dev Derive the location of a mapping element from the key.
     */
    function deriveMapping(bytes32 slot, string memory key) internal pure returns (bytes32 result) {
        assembly ("memory-safe") {
            let length := mload(key)
            let begin := add(key, 0x20)
            let end := add(begin, length)
            let cache := mload(end)
            mstore(end, slot)
            result := keccak256(begin, add(length, 0x20))
            mstore(end, cache)
        }
    }

    /**
     * @dev Derive the location of a mapping element from the key.
     */
    function deriveMapping(bytes32 slot, bytes memory key) internal pure returns (bytes32 result) {
        assembly ("memory-safe") {
            let length := mload(key)
            let begin := add(key, 0x20)
            let end := add(begin, length)
            let cache := mload(end)
            mstore(end, slot)
            result := keccak256(begin, add(length, 0x20))
            mstore(end, cache)
        }
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/IERC165.sol)

pragma solidity >=0.4.16;

/**
 * @dev Interface of the ERC-165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[ERC].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

Settings
{
  "remappings": [
    "@aave-v3-core/contracts/=lib/aave-v3-core/contracts/",
    "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
    "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
    "@uniswap-v2/v2-periphery/=lib/v2-periphery/contracts/",
    "@solady/src/=lib/solady/src/",
    "forge-std/=lib/forge-std/src/",
    "@layerzerolabs/oapp-evm/=lib/devtools/packages/oapp-evm/",
    "@layerzerolabs/oft-evm/=lib/devtools/packages/oft-evm/",
    "@layerzerolabs/oapp-evm-upgradeable/=lib/devtools/packages/oapp-evm-upgradeable/",
    "@layerzerolabs/lz-evm-oapp-v2/=lib/LayerZero-v2/packages/layerzero-v2/evm/oapp/",
    "@layerzerolabs/lz-evm-protocol-v2/=lib/LayerZero-v2/packages/layerzero-v2/evm/protocol/",
    "@layerzerolabs/lz-evm-messagelib-v2/=lib/LayerZero-v2/packages/layerzero-v2/evm/messagelib/",
    "solidity-bytes-utils/=lib/solidity-bytes-utils/",
    "LayerZero-v2/=lib/LayerZero-v2/",
    "aave-v3-core/=lib/aave-v3-core/",
    "devtools/=lib/devtools/packages/toolbox-foundry/src/",
    "ds-test/=lib/LayerZero-v2/lib/forge-std/lib/ds-test/src/",
    "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
    "halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/",
    "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/",
    "solady/=lib/solady/src/",
    "v2-periphery/=lib/v2-periphery/contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 4000
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "prague",
  "viaIR": true
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"bytes32","name":"selector","type":"bytes32"}],"name":"AccountingFailed","type":"error"},{"inputs":[],"name":"AccountingViaOracles","type":"error"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"AdapterNotAllowed","type":"error"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"AlreadySet","type":"error"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"CrossChainRequestWasntFulfilled","type":"error"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FacetHasBalance","type":"error"},{"inputs":[],"name":"FacetNotInitializing","type":"error"},{"inputs":[],"name":"FinalizationCallFailed","type":"error"},{"inputs":[],"name":"InvalidActionType","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"InvalidParameters","type":"error"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"}],"name":"NoOracleForSpoke","type":"error"},{"inputs":[],"name":"NotEnoughMsgValueProvided","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[],"name":"OnlyCrossChainAccountingManager","type":"error"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint32","name":"","type":"uint32"}],"name":"OracleWasntSetForSpoke","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[],"name":"RequestAlreadyFinalized","type":"error"},{"inputs":[],"name":"RequestTimedOut","type":"error"},{"inputs":[],"name":"RequestWasntFulfilled","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"UnauthorizedAccess","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"guid","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"sumOfSpokesUsdValue","type":"uint256"},{"indexed":false,"internalType":"bool","name":"readSuccess","type":"bool"}],"name":"AccountingInfoUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bool","name":"isTrue","type":"bool"}],"name":"OracleCrossChainAccountingUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"accountingBridgeFacet","outputs":[{"internalType":"uint256","name":"sum","type":"uint256"},{"internalType":"bool","name":"isPositive","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"adapter","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"bridgeSpecificParams","type":"bytes"}],"name":"executeBridging","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"facetName","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"facetVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"guid","type":"bytes32"}],"name":"finalizeRequest","outputs":[{"internalType":"bytes","name":"result","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"guid","type":"bytes32"}],"name":"getRequestInfo","outputs":[{"components":[{"internalType":"address","name":"initiator","type":"address"},{"internalType":"uint64","name":"timestamp","type":"uint64"},{"internalType":"enum MoreVaultsLib.ActionType","name":"actionType","type":"uint8"},{"internalType":"bytes","name":"actionCallData","type":"bytes"},{"internalType":"bool","name":"fulfilled","type":"bool"},{"internalType":"bool","name":"finalized","type":"bool"},{"internalType":"uint256","name":"totalAssets","type":"uint256"}],"internalType":"struct MoreVaultsLib.CrossChainRequestInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum MoreVaultsLib.ActionType","name":"actionType","type":"uint8"},{"internalType":"bytes","name":"actionCallData","type":"bytes"},{"internalType":"bytes","name":"extraOptions","type":"bytes"}],"name":"initVaultActionRequest","outputs":[{"internalType":"bytes32","name":"guid","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"","type":"bytes"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"isReplacing","type":"bool"}],"name":"onFacetRemoval","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"extraOptions","type":"bytes"}],"name":"quoteAccountingFee","outputs":[{"internalType":"uint256","name":"nativeFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"isTrue","type":"bool"}],"name":"setOraclesCrossChainAccounting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"guid","type":"bytes32"},{"internalType":"uint256","name":"sumOfSpokesUsdValue","type":"uint256"},{"internalType":"bool","name":"readSuccess","type":"bool"}],"name":"updateAccountingInfoForRequest","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6080806040523460395760017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005561359b908161003e8239f35b5f80fdfe6080806040526004361015610012575f80fd5b5f905f3560e01c908163135df66214612b41575080632dc6a66d146123e9578063439fab91146120785780635b6f4d01146120195780635c975abb14611fd85780635d381d3c14611ddd57806382d67e5a14611bd4578063adc209eb14611b75578063c015e57a1461171c578063c870cd20146113a7578063d73c99dd146110dd578063e439b6041461080c5763ec86885d146100ad575f80fd5b602060031936011261080957600435906100c5613363565b6060918082527fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d44060205260408220926040519061010182612e78565b8454946001600160a01b03861683526020830167ffffffffffffffff8760a01c16815261013860ff604086019860e01c168861312b565b600182019360405194858882549261014f84613137565b80845293600181169081156107e757506001146107a6575b5061017492500386612eb0565b83810194855260c0600360028501549460ff86161515608085015260ff60a085019660081c161515865201549101528486527fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d44060205260ff6002604088200154161561077e5767ffffffffffffffff610e109151160167ffffffffffffffff811161076a5767ffffffffffffffff42911610610742575161071a57827fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d4415583855160068110156106f25761039d575050829350916102c26102b46102648394955160208082518301019101613246565b6040517f6e553f65000000000000000000000000000000000000000000000000000000006020820190815260248201939093526001600160a01b0390911660448201529092909182906064820190565b03601f198101835282612eb0565b519082305af1906102d16131f1565b915b1561037557916103719281527fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d4406020526002604082200161010061ff00198254161790557fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d4415560017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055604051918291602083526020830190612e53565b0390f35b6004837f6a176703000000000000000000000000000000000000000000000000000000008152fd5b855160068110156106f2576004036104a25750508293506103cb909291925160208082518301019101613260565b919392906040519061040f60208301937f98c601aa00000000000000000000000000000000000000000000000000000000855260606024850152608484019061305e565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc83820301604484015260208088519283815201970190865b818110610489575050508185966001600160a01b036104759316606483015203601f198101835282612eb0565b5191305af1906104836131f1565b916102d3565b825189526020988901988b985090920191600101610448565b855160068110156106f257600103610535575050829350916105266102b46104d68394955160208082518301019101613246565b6040517f94bf804d000000000000000000000000000000000000000000000000000000006020820190815260248201939093526001600160a01b0390911660448201529092909182906064820190565b519082305af1906104836131f1565b85519560068710156106f2579495939486946002036105bf5750505061052661056983925160208082518301019101613220565b6040517fb460af94000000000000000000000000000000000000000000000000000000006020820190815260248201949094526001600160a01b03928316604482015291166064820152909181608481016102b4565b80919295945051600681101561070657869392919060030361064e575050819293506105f8610526915160208082518301019101613220565b6040517fba087652000000000000000000000000000000000000000000000000000000006020820190815260248201949094526001600160a01b03928316604482015291166064820152909181608481016102b4565b9092505160068110156106f25790600586921461066d575b50506102d3565b909150516020818051810103126106ee5761068b60208392016131c3565b6040516bffffffffffffffffffffffff60208201927fae275dce000000000000000000000000000000000000000000000000000000008452166024820152602481526106d8604482612eb0565b519082305af16106e66131f1565b50835f610666565b5080fd5b602486634e487b7160e01b81526021600452fd5b602487634e487b7160e01b81526021600452fd5b6004847ff1a60193000000000000000000000000000000000000000000000000000000008152fd5b6004857f6512950c000000000000000000000000000000000000000000000000000000008152fd5b602486634e487b7160e01b81526011600452fd5b6004867f93bb4f75000000000000000000000000000000000000000000000000000000008152fd5b8a525060208920909189915b8183106107cb575050906020610174928201015f610167565b6020919350806001915483858c010152019101909187926107b2565b6020935061017495925060ff1991501682840152151560051b8201015f610167565b80fd5b503461080957602060031936011261080957610826612e16565b6001600160a01b037fb1f8eb8d5f5694fe92802e1062618177031a72ddac422b154aa1cc0abdb48a31541633036110b5576001600160a01b037fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d4395460081c169082604051927f72607537000000000000000000000000000000000000000000000000000000008452602084600481845afa9081156110aa57829161106d575b6040517f697bc61e00000000000000000000000000000000000000000000000000000000815263ffffffff909216600483015230602483015290935083908180604481015b03915afa918215611062578390849361103b575b5060ff7fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d43f5460081c16159282151593801585146110135783908161100b575b50610dff575b505015610b4a577fffffffff0000000000000000000000000000000000000000000000000000000060405160208101907f6163636f756e74696e67427269646765466163657428290000000000000000008252601781526109c5603782612eb0565b519020167fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d4205468010000000000000000811015610b3657600181017fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d420557fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d42054811015610b22577fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d42084527f15c18ae639c6f22673532306d064f0a75223f72bb10edc7169d6f6fced78facb01805490915f19600386901b90811b19909216911b1790555b7fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d43f5461ff001961ff008360081b169116177fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d43f557f5e87ea5a5358e2884bc0d6024c3349226d48734e82c903471ced06805ec9160e8280a280f35b602484634e487b7160e01b81526032600452fd5b602484634e487b7160e01b81526041600452fd5b7fffffffff0000000000000000000000000000000000000000000000000000000060405160208101907f6163636f756e74696e6742726964676546616365742829000000000000000000825260178152610ba5603782612eb0565b5190201690825b7fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d4205480821015610df65783610c01837fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d4206131dc565b90549060031b1c14610c165750600101610bac565b9091928480604051602081019084825260048152610c35602482612eb0565b5190305afa90610c436131f1565b9115610dcb575060208151918180820193849201010312610dc75751620186a08111610d9c57505f198101908111610d8857610cd3610ca5610ce9927fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d4206131dc565b90549060031b1c927fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d4206131dc565b81939154905f199060031b92831b921b19161790565b90557fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d420548015610d74575f1901610d40817fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d4206131dc565b5f1982549160031b1b191690557fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d42055610aa8565b602483634e487b7160e01b81526031600452fd5b602484634e487b7160e01b81526011600452fd5b7f67e7be8f000000000000000000000000000000000000000000000000000000008552600452602484fd5b5f80fd5b7f712f7784000000000000000000000000000000000000000000000000000000008652600452602485fd5b50509050610aa8565b939283929192916001600160a01b037fb1f8eb8d5f5694fe92802e1062618177031a72ddac422b154aa1cc0abdb48a345416925b8651811015610ffd576040517f7dc0d1d0000000000000000000000000000000000000000000000000000000008152602081600481885afa908115610fc457610eeb6001600160a01b03926040928a91610fcf575b5063ffffffff610e98868b61319b565b511683519485809481937f528e43ae000000000000000000000000000000000000000000000000000000008352306004840190929163ffffffff6020916001600160a01b03604085019616845216910152565b0392165afa8015610fc4578790610f52575b6001600160a01b039150511615610f1657600101610e33565b8563ffffffff610f286024938861319b565b51167f02e36be6000000000000000000000000000000000000000000000000000000008252600452fd5b506040813d8211610fbc575b81610f6b60409383612eb0565b81010312610fb85760405190610f8082612e94565b80516001600160a01b0381168103610fb45760208392610faa926001600160a01b039552016131c3565b6020820152610efd565b8880fd5b8680fd5b3d9150610f5e565b6040513d89823e3d90fd5b610ff0915060203d8111610ff6575b610fe88183612eb0565b81019061317c565b5f610e88565b503d610fde565b509250929350505f80610963565b90505f61095d565b6004867fa741a045000000000000000000000000000000000000000000000000000000008152fd5b905061105a9192503d8085833e6110528183612eb0565b810190612f75565b91905f61091e565b6040513d85823e3d90fd5b90506020843d6020116110a2575b8161108860209383612eb0565b810103126106ee5761109c61090a94612ed3565b906108c5565b3d915061107b565b6040513d84823e3d90fd5b6004827f344fd586000000000000000000000000000000000000000000000000000000008152fd5b5034610809578060031936011261080957806001600160a01b037fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d4395460081c16604051907f72607537000000000000000000000000000000000000000000000000000000008252602082600481845afa91821561106257839261135f575b506040517f697bc61e00000000000000000000000000000000000000000000000000000000815263ffffffff9092166004830152306024830152909190819083908180604481015b03915afa9182156113525781908293611333575b5081936001600160a01b037fb1f8eb8d5f5694fe92802e1062618177031a72ddac422b154aa1cc0abdb48a345416905b8451861015611322576040517f7dc0d1d0000000000000000000000000000000000000000000000000000000008152602081600481865afa9081156112fa576112a06001600160a01b03926020928891611305575b5063ffffffff61124c8b8961319b565b51166040519485809481937f4333dfb5000000000000000000000000000000000000000000000000000000008352306004840190929163ffffffff6020916001600160a01b03604085019616845216910152565b0392165afa9081156112fa5785916112c8575b506112c09060019261316f565b9501946111e7565b90506020813d82116112f2575b816112e260209383612eb0565b81010312610dc7575160016112b3565b3d91506112d5565b6040513d87823e3d90fd5b61131c9150833d8111610ff657610fe88183612eb0565b5f61123c565b604080519182526001602083015290f35b905061134a9192503d8084833e6110528183612eb0565b91905f6111b7565b50604051903d90823e3d90fd5b9091506020813d60201161139f575b8161137b60209383612eb0565b8101031261139b579180916113926111a394612ed3565b9250909261115b565b8280fd5b3d915061136e565b503461080957606060031936011261080957600435604435602435811515808303611718576001600160a01b036113dc6133da565b1633036116f0578261145f575b906040916114517f0a5ea785af23e5274baa6073ee030c55c4ca83d705180cefe1e0df8af0ce0e2b948688527fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d4406020526002858920019060ff60ff1983541691151516179055565b82519182526020820152a280f35b600460206001600160a01b037fb1f8eb8d5f5694fe92802e1062618177031a72ddac422b154aa1cc0abdb48a345416604051928380927f7dc0d1d00000000000000000000000000000000000000000000000000000000082525afa9081156116e55786916116c6575b506001600160a01b037f0773e532dfede91f04b12a73d3d2acd361424f41f76b4fb79f090161e36b4e005416906040517f313ce567000000000000000000000000000000000000000000000000000000008152602081600481865afa80156116bb57889061167a575b60ff91501691604d8311611666576001600160a01b039291602460209260405195869384927fb3596f070000000000000000000000000000000000000000000000000000000084526004840152165afa918215610fc457879261160c575b507f0a5ea785af23e5274baa6073ee030c55c4ca83d705180cefe1e0df8af0ce0e2b946115c7604095949361145193600a0a866134b2565b8789527fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d4406020526115ff6003878b200191825461316f565b90559450509091506113e9565b939291506020843d60201161165e575b8161162960209383612eb0565b81010312610dc757925191929091907f0a5ea785af23e5274baa6073ee030c55c4ca83d705180cefe1e0df8af0ce0e2b61158f565b3d915061161c565b602488634e487b7160e01b81526011600452fd5b506020813d6020116116b3575b8161169460209383612eb0565b810103126116af575160ff811681036116af5760ff90611531565b8780fd5b3d9150611687565b6040513d8a823e3d90fd5b6116df915060203d602011610ff657610fe88183612eb0565b5f6114c8565b6040513d88823e3d90fd5b6004857f5409b66b000000000000000000000000000000000000000000000000000000008152fd5b8480fd5b506080600319360112610dc7576004356001600160a01b038116809103610dc7576024356001600160a01b038116809103610dc75760443560643567ffffffffffffffff8111610dc757611774903690600401612e25565b92909161177f613310565b6001600160a01b037fb1f8eb8d5f5694fe92802e1062618177031a72ddac422b154aa1cc0abdb48a32541633141580611b41575b611b19576117bf613310565b600160ff197fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005416177fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a1602460206001600160a01b037fb1f8eb8d5f5694fe92802e1062618177031a72ddac422b154aa1cc0abdb48a345416604051928380927f0d8d0f630000000000000000000000000000000000000000000000000000000082528a60048301525afa908115611966575f91611ade575b5015611ab2576040517f095ea7b3000000000000000000000000000000000000000000000000000000005f52856004528160245260205f60448180875af19060015f5114821615611aa3575b60405215611971575b5050823b15610dc757611944925f926040518095819482937f3dde08670000000000000000000000000000000000000000000000000000000084526020600485015260248401916130d3565b039134905af1801561196657611958575080f35b61196491505f90612eb0565b005b6040513d5f823e3d90fd5b6040517f095ea7b3000000000000000000000000000000000000000000000000000000005f52856004525f60245260205f60448180875af19060015f5114821615611a8b575b60405215611a5f57604051907f095ea7b3000000000000000000000000000000000000000000000000000000005f528560045260245260205f60448180865af19060015f5114821615611a3e575b60405215611a1357806118f8565b7f5274afe7000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b906001811516611a5657823b15153d15161690611a05565b503d5f823e3d90fd5b507f5274afe7000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b906001811516611a5657833b15153d151616906119b7565b90833b15153d151616906118ef565b847ffae021e8000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b90506020813d602011611b11575b81611af960209383612eb0565b81010312610dc757518015158103610dc7575f6118a3565b3d9150611aec565b7f344fd586000000000000000000000000000000000000000000000000000000005f5260045ffd5b50336001600160a01b037fb1f8eb8d5f5694fe92802e1062618177031a72ddac422b154aa1cc0abdb48a31541614156117b3565b34610dc7575f600319360112610dc757610371604051611b96604082612eb0565b600581527f312e302e300000000000000000000000000000000000000000000000000000006020820152604051918291602083526020830190612e53565b34610dc7576020600319360112610dc7575f60c0604051611bf481612e78565b8281528260208201528260408201526060808201528260808201528260a082015201526004355f527fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d44060205260405f2060405190611c5182612e78565b8054906001600160a01b03821683526020830167ffffffffffffffff8360a01c168152611c8860ff604086019460e01c168461312b565b600182019260405193845f825492611c9f84613137565b8084529360018116908115611dbb5750600114611d77575b50611cc492500385612eb0565b6060850193845260028301549067ffffffffffffffff6003608088019560ff85161515875260ff60a08a019560081c161515855201549360c088019485526001600160a01b036040519860208a525116602089015251166040870152516006811015611d63578594611d489160608701525160e06080870152610100860190612e53565b9251151560a085015251151560c08401525160e08301520390f35b634e487b7160e01b5f52602160045260245ffd5b90505f9291925260205f20905f915b818310611d9f575050906020611cc49282010188611cb7565b6020919350806001915483858b01015201910190918692611d86565b60209350611cc495925060ff1991501682840152151560051b82010188611cb7565b34610dc7576020600319360112610dc75760043567ffffffffffffffff8111610dc757611e0e903690600401612e25565b906001600160a01b037fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d4395460081c16906040517f72607537000000000000000000000000000000000000000000000000000000008152602081600481865afa908115611966575f91611f97575b506040517f697bc61e00000000000000000000000000000000000000000000000000000000815263ffffffff9091166004820152306024820152915f9083908180604481015b03915afa8015611966576040925f905f92611f7a575b506001600160a01b03611ee86133da565b1691611f228551968795869485947f55fdf55a000000000000000000000000000000000000000000000000000000008652600486016130f3565b03915afa8015611966575f90611f3f575b60209051604051908152f35b5060403d604011611f73575b611f558183612eb0565b810190604081830312610dc757602091611f6e91613036565b611f33565b503d611f4b565b9050611f9091503d805f833e6110528183612eb0565b9085611ed7565b90506020813d602011611fd0575b81611fb260209383612eb0565b81010312610dc757611ec192611fc85f92612ed3565b915092611e7b565b3d9150611fa5565b34610dc7575f600319360112610dc757602060ff7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f0330054166040519015158152f35b34610dc7575f600319360112610dc75761037160405161203a604082612eb0565b600b81527f42726964676546616365740000000000000000000000000000000000000000006020820152604051918291602083526020830190612e53565b34610dc7576020600319360112610dc75760043567ffffffffffffffff8111610dc7576120a9903690600401612e25565b50507f81f35766bfb459eee5195947675af325872ddcb047cc8eea07597137a43dba175460ff8160081c16805f146123e057303b15155b6123b85715908161236a575b507ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460ff8160401c16159067ffffffffffffffff811680159081612362575b6001149081612358575b15908161234f575b50612327578160017fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000008316177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00556122d2575b507f25ce4ad5000000000000000000000000000000000000000000000000000000005f527fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d4216020527f068ad2b3d244cfb331455d41a4346fa1155f72ee85e27f1144f86dd0b4413549805460ff1916600117905561223c575b61221057005b7f81f35766bfb459eee5195947675af325872ddcb047cc8eea07597137a43dba17805461ff0019169055005b7fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054167ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a161220a565b7fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000001668010000000000000001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005582612191565b7ff92ee8a9000000000000000000000000000000000000000000000000000000005f5260045ffd5b9050158461213e565b303b159150612136565b83915061212c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016610101177f81f35766bfb459eee5195947675af325872ddcb047cc8eea07597137a43dba1755816120ec565b7f0dc149f0000000000000000000000000000000000000000000000000000000005f5260045ffd5b60ff82166120e0565b6060600319360112610dc7576004356006811015610dc75760243567ffffffffffffffff8111610dc757612421903690600401612e25565b9060443567ffffffffffffffff8111610dc757612442903690600401612e25565b61244d939193613310565b612455613363565b5f936001600160a01b037fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d4395460081c16916040517f72607537000000000000000000000000000000000000000000000000000000008152602081600481875afa908115611966575f91612b00575b506040517f697bc61e00000000000000000000000000000000000000000000000000000000815263ffffffff9091166004820152306024820152925f9084908180604481015b03915afa908115611966575f935f92612ae1575b508151612554575b60208760017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055604051908152f35b9091929394955060ff7fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d43f5460081c16612ab957604051927f01e1d114000000000000000000000000000000000000000000000000000000008452602084600481305afa938415611966575f94612a85575b50604051946125d386612e78565b338652602086019267ffffffffffffffff4216845260408701976125f78b8a61312b565b6126008161301a565b9961260e6040519b8c612eb0565b818b523682820111610dc757815f92602092838e01378b0101526060870198895260808701945f865260a088019a5f8c5260c089019788526001600160a01b036126566133da565b16906040805180937f55fdf55a0000000000000000000000000000000000000000000000000000000082528180612693898c8c8b600486016130f3565b03915afa918215611966575f92612a46575b506004146129e8575b509061270d6080939261273161271f966001600160a01b036126ce6133da565b1694604051988997889687967f09e14bb70000000000000000000000000000000000000000000000000000000088528b6004890152608488019061305e565b9060031987830301602488015261309a565b916003198584030160448601526130d3565b336064830152039134905af1908115611966575f91612969575b505194855f527fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d4406020526001600160a01b0360405f209551167bffffffffffffffff00000000000000000000000000000000000000008654935160a01b1691516006811015611d63577cff000000000000000000000000000000000000000000000000000000007fffffff00000000000000000000000000000000000000000000000000000000009160e01b16931617171783556001830194519586519567ffffffffffffffff8711612955576128228154613137565b97601f8911612910575b602098508890601f89116001146128ab5797809160039798995f926128a0575b50505f198260011b92881b1c19161790555b61287c6002860192511515839060ff60ff1983541691151516179055565b51815461ff00191690151560081b61ff001617905551910155828080808080612525565b015190508a8061284c565b90601f19891691835f52815f20925f5b8181106128f9575091600193918b60039a9b9c94106128e2575b505050811b01905561285e565b01515f1960f8848b1b161c191690558a80806128d5565b92938c6001819287860151815501950193016128bb565b815f5260205f20601f890160051c81019960208a1061294b575b601f0160051c01985b898110612940575061282c565b5f8155600101612933565b909950899061292a565b634e487b7160e01b5f52604160045260245ffd5b905060803d6080116129e1575b6129808183612eb0565b810190608081830312610dc757604051916060830183811067ffffffffffffffff8211176129555760405281518352602082015167ffffffffffffffff81168103610dc75760208401526129d691604001613036565b60408201528861274b565b503d612976565b612a1090612a048c959493955160208082518301019101613260565b9392505050519061316f565b3410612a1e5790918b6126ae565b7f1a041778000000000000000000000000000000000000000000000000000000005f5260045ffd5b90915060403d604011612a7e575b612a5e8183612eb0565b810190604081830312610dc757600491612a7791613036565b91906126a5565b503d612a54565b9093506020813d602011612ab1575b81612aa160209383612eb0565b81010312610dc7575192886125c5565b3d9150612a94565b7fe7ce5391000000000000000000000000000000000000000000000000000000005f5260045ffd5b909350612af891503d805f833e6110528183612eb0565b90928861251d565b90506020813d602011612b39575b81612b1b60209383612eb0565b81010312610dc75761250993612b315f92612ed3565b9150936124c3565b3d9150612b0e565b34610dc7576020600319360112610dc7577fffffffff00000000000000000000000000000000000000000000000000000000612b7b612e16565b917f25ce4ad5000000000000000000000000000000000000000000000000000000005f527fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d42160205260405f2060ff19815416905560208101907f6163636f756e74696e6742726964676546616365742829000000000000000000825260178152612c06603782612eb0565b51902016905f5b7fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d42054808210156119645783612c62837fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d4206131dc565b90549060031b1c14612c775750600101612c0d565b9192909215612d6f575b505f198101908111612d5b57610cd3610ca5612cbd927fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d4206131dc565b90557fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d420548015612d47575f1901612d14817fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d4206131dc565b5f1982549160031b1b191690557fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d420555f80f35b634e487b7160e01b5f52603160045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b5f80604051602081019084825260048152612d8b602482612eb0565b5190305afa90612d996131f1565b9115612deb575060208151918180820193849201010312610dc75751620186a0811115612c81577f67e7be8f000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b7f712f7784000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b600435908115158203610dc757565b9181601f84011215610dc75782359167ffffffffffffffff8311610dc75760208381860195010111610dc757565b90601f19601f602080948051918291828752018686015e5f8582860101520116010190565b60e0810190811067ffffffffffffffff82111761295557604052565b6040810190811067ffffffffffffffff82111761295557604052565b90601f601f19910116810190811067ffffffffffffffff82111761295557604052565b519063ffffffff82168203610dc757565b67ffffffffffffffff81116129555760051b60200190565b51906001600160a01b0382168203610dc757565b9080601f83011215610dc7578151612f2781612ee4565b92612f356040519485612eb0565b81845260208085019260051b820101928311610dc757602001905b828210612f5d5750505090565b60208091612f6a84612efc565b815201910190612f50565b919091604081840312610dc757805167ffffffffffffffff8111610dc757810183601f82011215610dc757805190612fac82612ee4565b91612fba6040519384612eb0565b80835260208084019160051b83010191868311610dc757602001905b8282106130025750505092602082015167ffffffffffffffff8111610dc757612fff9201612f10565b90565b6020809161300f84612ed3565b815201910190612fd6565b67ffffffffffffffff811161295557601f01601f191660200190565b9190826040910312610dc75760405161304e81612e94565b6020808294805184520151910152565b90602080835192838152019201905f5b81811061307b5750505090565b82516001600160a01b031684526020938401939092019160010161306e565b90602080835192838152019201905f5b8181106130b75750505090565b825163ffffffff168452602093840193909201916001016130aa565b601f8260209493601f1993818652868601375f8582860101520116010190565b9290612fff949261310f61311d9260608752606087019061305e565b90858203602087015261309a565b9260408185039101526130d3565b6006821015611d635752565b90600182811c92168015613165575b602083101461315157565b634e487b7160e01b5f52602260045260245ffd5b91607f1691613146565b91908201809211612d5b57565b90816020910312610dc757516001600160a01b0381168103610dc75790565b80518210156131af5760209160051b010190565b634e487b7160e01b5f52603260045260245ffd5b51906bffffffffffffffffffffffff82168203610dc757565b80548210156131af575f5260205f2001905f90565b3d1561321b573d906132028261301a565b916132106040519384612eb0565b82523d5f602084013e565b606090565b90816060910312610dc757805191612fff604061323f60208501612efc565b9301612efc565b9190826040910312610dc757612fff602083519301612efc565b919091608081840312610dc757805167ffffffffffffffff8111610dc7578361328a918301612f10565b92602082015167ffffffffffffffff8111610dc75782019080601f83011215610dc75781516132b881612ee4565b926132c66040519485612eb0565b81845260208085019260051b820101928311610dc757602001905b828210613300575050509160606132fa60408401612efc565b92015190565b81518152602091820191016132e1565b60ff7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300541661333b57565b7fd93c0665000000000000000000000000000000000000000000000000000000005f5260045ffd5b60027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0054146133b25760027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b7f3ee5aeb5000000000000000000000000000000000000000000000000000000005f5260045ffd5b6001600160a01b037fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d43f5460101c1680156134115790565b50600460206001600160a01b037fb1f8eb8d5f5694fe92802e1062618177031a72ddac422b154aa1cc0abdb48a345416604051928380927f363a20940000000000000000000000000000000000000000000000000000000082525afa908115611966575f9161347e575090565b90506020813d6020116134aa575b8161349960209383612eb0565b81010312610dc757612fff90612efc565b3d915061348c565b90915f198383099280830292838086109503948086039514613543578483111561352b5790829109815f0382168092046002816003021880820260020302808202600203028082026002030280820260020302808202600203028091026002030293600183805f03040190848311900302920304170290565b82634e487b715f52156003026011186020526024601cfd5b505080925015613551570490565b634e487b7160e01b5f52601260045260245ffdfea264697066735822122018dceca79aaa649a4dcc0816c12941568d4a5fcbcc78d04ca18be1cbfc5dad4b64736f6c634300081c0033

Deployed Bytecode

0x6080806040526004361015610012575f80fd5b5f905f3560e01c908163135df66214612b41575080632dc6a66d146123e9578063439fab91146120785780635b6f4d01146120195780635c975abb14611fd85780635d381d3c14611ddd57806382d67e5a14611bd4578063adc209eb14611b75578063c015e57a1461171c578063c870cd20146113a7578063d73c99dd146110dd578063e439b6041461080c5763ec86885d146100ad575f80fd5b602060031936011261080957600435906100c5613363565b6060918082527fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d44060205260408220926040519061010182612e78565b8454946001600160a01b03861683526020830167ffffffffffffffff8760a01c16815261013860ff604086019860e01c168861312b565b600182019360405194858882549261014f84613137565b80845293600181169081156107e757506001146107a6575b5061017492500386612eb0565b83810194855260c0600360028501549460ff86161515608085015260ff60a085019660081c161515865201549101528486527fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d44060205260ff6002604088200154161561077e5767ffffffffffffffff610e109151160167ffffffffffffffff811161076a5767ffffffffffffffff42911610610742575161071a57827fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d4415583855160068110156106f25761039d575050829350916102c26102b46102648394955160208082518301019101613246565b6040517f6e553f65000000000000000000000000000000000000000000000000000000006020820190815260248201939093526001600160a01b0390911660448201529092909182906064820190565b03601f198101835282612eb0565b519082305af1906102d16131f1565b915b1561037557916103719281527fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d4406020526002604082200161010061ff00198254161790557fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d4415560017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055604051918291602083526020830190612e53565b0390f35b6004837f6a176703000000000000000000000000000000000000000000000000000000008152fd5b855160068110156106f2576004036104a25750508293506103cb909291925160208082518301019101613260565b919392906040519061040f60208301937f98c601aa00000000000000000000000000000000000000000000000000000000855260606024850152608484019061305e565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc83820301604484015260208088519283815201970190865b818110610489575050508185966001600160a01b036104759316606483015203601f198101835282612eb0565b5191305af1906104836131f1565b916102d3565b825189526020988901988b985090920191600101610448565b855160068110156106f257600103610535575050829350916105266102b46104d68394955160208082518301019101613246565b6040517f94bf804d000000000000000000000000000000000000000000000000000000006020820190815260248201939093526001600160a01b0390911660448201529092909182906064820190565b519082305af1906104836131f1565b85519560068710156106f2579495939486946002036105bf5750505061052661056983925160208082518301019101613220565b6040517fb460af94000000000000000000000000000000000000000000000000000000006020820190815260248201949094526001600160a01b03928316604482015291166064820152909181608481016102b4565b80919295945051600681101561070657869392919060030361064e575050819293506105f8610526915160208082518301019101613220565b6040517fba087652000000000000000000000000000000000000000000000000000000006020820190815260248201949094526001600160a01b03928316604482015291166064820152909181608481016102b4565b9092505160068110156106f25790600586921461066d575b50506102d3565b909150516020818051810103126106ee5761068b60208392016131c3565b6040516bffffffffffffffffffffffff60208201927fae275dce000000000000000000000000000000000000000000000000000000008452166024820152602481526106d8604482612eb0565b519082305af16106e66131f1565b50835f610666565b5080fd5b602486634e487b7160e01b81526021600452fd5b602487634e487b7160e01b81526021600452fd5b6004847ff1a60193000000000000000000000000000000000000000000000000000000008152fd5b6004857f6512950c000000000000000000000000000000000000000000000000000000008152fd5b602486634e487b7160e01b81526011600452fd5b6004867f93bb4f75000000000000000000000000000000000000000000000000000000008152fd5b8a525060208920909189915b8183106107cb575050906020610174928201015f610167565b6020919350806001915483858c010152019101909187926107b2565b6020935061017495925060ff1991501682840152151560051b8201015f610167565b80fd5b503461080957602060031936011261080957610826612e16565b6001600160a01b037fb1f8eb8d5f5694fe92802e1062618177031a72ddac422b154aa1cc0abdb48a31541633036110b5576001600160a01b037fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d4395460081c169082604051927f72607537000000000000000000000000000000000000000000000000000000008452602084600481845afa9081156110aa57829161106d575b6040517f697bc61e00000000000000000000000000000000000000000000000000000000815263ffffffff909216600483015230602483015290935083908180604481015b03915afa918215611062578390849361103b575b5060ff7fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d43f5460081c16159282151593801585146110135783908161100b575b50610dff575b505015610b4a577fffffffff0000000000000000000000000000000000000000000000000000000060405160208101907f6163636f756e74696e67427269646765466163657428290000000000000000008252601781526109c5603782612eb0565b519020167fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d4205468010000000000000000811015610b3657600181017fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d420557fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d42054811015610b22577fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d42084527f15c18ae639c6f22673532306d064f0a75223f72bb10edc7169d6f6fced78facb01805490915f19600386901b90811b19909216911b1790555b7fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d43f5461ff001961ff008360081b169116177fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d43f557f5e87ea5a5358e2884bc0d6024c3349226d48734e82c903471ced06805ec9160e8280a280f35b602484634e487b7160e01b81526032600452fd5b602484634e487b7160e01b81526041600452fd5b7fffffffff0000000000000000000000000000000000000000000000000000000060405160208101907f6163636f756e74696e6742726964676546616365742829000000000000000000825260178152610ba5603782612eb0565b5190201690825b7fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d4205480821015610df65783610c01837fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d4206131dc565b90549060031b1c14610c165750600101610bac565b9091928480604051602081019084825260048152610c35602482612eb0565b5190305afa90610c436131f1565b9115610dcb575060208151918180820193849201010312610dc75751620186a08111610d9c57505f198101908111610d8857610cd3610ca5610ce9927fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d4206131dc565b90549060031b1c927fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d4206131dc565b81939154905f199060031b92831b921b19161790565b90557fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d420548015610d74575f1901610d40817fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d4206131dc565b5f1982549160031b1b191690557fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d42055610aa8565b602483634e487b7160e01b81526031600452fd5b602484634e487b7160e01b81526011600452fd5b7f67e7be8f000000000000000000000000000000000000000000000000000000008552600452602484fd5b5f80fd5b7f712f7784000000000000000000000000000000000000000000000000000000008652600452602485fd5b50509050610aa8565b939283929192916001600160a01b037fb1f8eb8d5f5694fe92802e1062618177031a72ddac422b154aa1cc0abdb48a345416925b8651811015610ffd576040517f7dc0d1d0000000000000000000000000000000000000000000000000000000008152602081600481885afa908115610fc457610eeb6001600160a01b03926040928a91610fcf575b5063ffffffff610e98868b61319b565b511683519485809481937f528e43ae000000000000000000000000000000000000000000000000000000008352306004840190929163ffffffff6020916001600160a01b03604085019616845216910152565b0392165afa8015610fc4578790610f52575b6001600160a01b039150511615610f1657600101610e33565b8563ffffffff610f286024938861319b565b51167f02e36be6000000000000000000000000000000000000000000000000000000008252600452fd5b506040813d8211610fbc575b81610f6b60409383612eb0565b81010312610fb85760405190610f8082612e94565b80516001600160a01b0381168103610fb45760208392610faa926001600160a01b039552016131c3565b6020820152610efd565b8880fd5b8680fd5b3d9150610f5e565b6040513d89823e3d90fd5b610ff0915060203d8111610ff6575b610fe88183612eb0565b81019061317c565b5f610e88565b503d610fde565b509250929350505f80610963565b90505f61095d565b6004867fa741a045000000000000000000000000000000000000000000000000000000008152fd5b905061105a9192503d8085833e6110528183612eb0565b810190612f75565b91905f61091e565b6040513d85823e3d90fd5b90506020843d6020116110a2575b8161108860209383612eb0565b810103126106ee5761109c61090a94612ed3565b906108c5565b3d915061107b565b6040513d84823e3d90fd5b6004827f344fd586000000000000000000000000000000000000000000000000000000008152fd5b5034610809578060031936011261080957806001600160a01b037fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d4395460081c16604051907f72607537000000000000000000000000000000000000000000000000000000008252602082600481845afa91821561106257839261135f575b506040517f697bc61e00000000000000000000000000000000000000000000000000000000815263ffffffff9092166004830152306024830152909190819083908180604481015b03915afa9182156113525781908293611333575b5081936001600160a01b037fb1f8eb8d5f5694fe92802e1062618177031a72ddac422b154aa1cc0abdb48a345416905b8451861015611322576040517f7dc0d1d0000000000000000000000000000000000000000000000000000000008152602081600481865afa9081156112fa576112a06001600160a01b03926020928891611305575b5063ffffffff61124c8b8961319b565b51166040519485809481937f4333dfb5000000000000000000000000000000000000000000000000000000008352306004840190929163ffffffff6020916001600160a01b03604085019616845216910152565b0392165afa9081156112fa5785916112c8575b506112c09060019261316f565b9501946111e7565b90506020813d82116112f2575b816112e260209383612eb0565b81010312610dc7575160016112b3565b3d91506112d5565b6040513d87823e3d90fd5b61131c9150833d8111610ff657610fe88183612eb0565b5f61123c565b604080519182526001602083015290f35b905061134a9192503d8084833e6110528183612eb0565b91905f6111b7565b50604051903d90823e3d90fd5b9091506020813d60201161139f575b8161137b60209383612eb0565b8101031261139b579180916113926111a394612ed3565b9250909261115b565b8280fd5b3d915061136e565b503461080957606060031936011261080957600435604435602435811515808303611718576001600160a01b036113dc6133da565b1633036116f0578261145f575b906040916114517f0a5ea785af23e5274baa6073ee030c55c4ca83d705180cefe1e0df8af0ce0e2b948688527fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d4406020526002858920019060ff60ff1983541691151516179055565b82519182526020820152a280f35b600460206001600160a01b037fb1f8eb8d5f5694fe92802e1062618177031a72ddac422b154aa1cc0abdb48a345416604051928380927f7dc0d1d00000000000000000000000000000000000000000000000000000000082525afa9081156116e55786916116c6575b506001600160a01b037f0773e532dfede91f04b12a73d3d2acd361424f41f76b4fb79f090161e36b4e005416906040517f313ce567000000000000000000000000000000000000000000000000000000008152602081600481865afa80156116bb57889061167a575b60ff91501691604d8311611666576001600160a01b039291602460209260405195869384927fb3596f070000000000000000000000000000000000000000000000000000000084526004840152165afa918215610fc457879261160c575b507f0a5ea785af23e5274baa6073ee030c55c4ca83d705180cefe1e0df8af0ce0e2b946115c7604095949361145193600a0a866134b2565b8789527fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d4406020526115ff6003878b200191825461316f565b90559450509091506113e9565b939291506020843d60201161165e575b8161162960209383612eb0565b81010312610dc757925191929091907f0a5ea785af23e5274baa6073ee030c55c4ca83d705180cefe1e0df8af0ce0e2b61158f565b3d915061161c565b602488634e487b7160e01b81526011600452fd5b506020813d6020116116b3575b8161169460209383612eb0565b810103126116af575160ff811681036116af5760ff90611531565b8780fd5b3d9150611687565b6040513d8a823e3d90fd5b6116df915060203d602011610ff657610fe88183612eb0565b5f6114c8565b6040513d88823e3d90fd5b6004857f5409b66b000000000000000000000000000000000000000000000000000000008152fd5b8480fd5b506080600319360112610dc7576004356001600160a01b038116809103610dc7576024356001600160a01b038116809103610dc75760443560643567ffffffffffffffff8111610dc757611774903690600401612e25565b92909161177f613310565b6001600160a01b037fb1f8eb8d5f5694fe92802e1062618177031a72ddac422b154aa1cc0abdb48a32541633141580611b41575b611b19576117bf613310565b600160ff197fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005416177fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a1602460206001600160a01b037fb1f8eb8d5f5694fe92802e1062618177031a72ddac422b154aa1cc0abdb48a345416604051928380927f0d8d0f630000000000000000000000000000000000000000000000000000000082528a60048301525afa908115611966575f91611ade575b5015611ab2576040517f095ea7b3000000000000000000000000000000000000000000000000000000005f52856004528160245260205f60448180875af19060015f5114821615611aa3575b60405215611971575b5050823b15610dc757611944925f926040518095819482937f3dde08670000000000000000000000000000000000000000000000000000000084526020600485015260248401916130d3565b039134905af1801561196657611958575080f35b61196491505f90612eb0565b005b6040513d5f823e3d90fd5b6040517f095ea7b3000000000000000000000000000000000000000000000000000000005f52856004525f60245260205f60448180875af19060015f5114821615611a8b575b60405215611a5f57604051907f095ea7b3000000000000000000000000000000000000000000000000000000005f528560045260245260205f60448180865af19060015f5114821615611a3e575b60405215611a1357806118f8565b7f5274afe7000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b906001811516611a5657823b15153d15161690611a05565b503d5f823e3d90fd5b507f5274afe7000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b906001811516611a5657833b15153d151616906119b7565b90833b15153d151616906118ef565b847ffae021e8000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b90506020813d602011611b11575b81611af960209383612eb0565b81010312610dc757518015158103610dc7575f6118a3565b3d9150611aec565b7f344fd586000000000000000000000000000000000000000000000000000000005f5260045ffd5b50336001600160a01b037fb1f8eb8d5f5694fe92802e1062618177031a72ddac422b154aa1cc0abdb48a31541614156117b3565b34610dc7575f600319360112610dc757610371604051611b96604082612eb0565b600581527f312e302e300000000000000000000000000000000000000000000000000000006020820152604051918291602083526020830190612e53565b34610dc7576020600319360112610dc7575f60c0604051611bf481612e78565b8281528260208201528260408201526060808201528260808201528260a082015201526004355f527fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d44060205260405f2060405190611c5182612e78565b8054906001600160a01b03821683526020830167ffffffffffffffff8360a01c168152611c8860ff604086019460e01c168461312b565b600182019260405193845f825492611c9f84613137565b8084529360018116908115611dbb5750600114611d77575b50611cc492500385612eb0565b6060850193845260028301549067ffffffffffffffff6003608088019560ff85161515875260ff60a08a019560081c161515855201549360c088019485526001600160a01b036040519860208a525116602089015251166040870152516006811015611d63578594611d489160608701525160e06080870152610100860190612e53565b9251151560a085015251151560c08401525160e08301520390f35b634e487b7160e01b5f52602160045260245ffd5b90505f9291925260205f20905f915b818310611d9f575050906020611cc49282010188611cb7565b6020919350806001915483858b01015201910190918692611d86565b60209350611cc495925060ff1991501682840152151560051b82010188611cb7565b34610dc7576020600319360112610dc75760043567ffffffffffffffff8111610dc757611e0e903690600401612e25565b906001600160a01b037fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d4395460081c16906040517f72607537000000000000000000000000000000000000000000000000000000008152602081600481865afa908115611966575f91611f97575b506040517f697bc61e00000000000000000000000000000000000000000000000000000000815263ffffffff9091166004820152306024820152915f9083908180604481015b03915afa8015611966576040925f905f92611f7a575b506001600160a01b03611ee86133da565b1691611f228551968795869485947f55fdf55a000000000000000000000000000000000000000000000000000000008652600486016130f3565b03915afa8015611966575f90611f3f575b60209051604051908152f35b5060403d604011611f73575b611f558183612eb0565b810190604081830312610dc757602091611f6e91613036565b611f33565b503d611f4b565b9050611f9091503d805f833e6110528183612eb0565b9085611ed7565b90506020813d602011611fd0575b81611fb260209383612eb0565b81010312610dc757611ec192611fc85f92612ed3565b915092611e7b565b3d9150611fa5565b34610dc7575f600319360112610dc757602060ff7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f0330054166040519015158152f35b34610dc7575f600319360112610dc75761037160405161203a604082612eb0565b600b81527f42726964676546616365740000000000000000000000000000000000000000006020820152604051918291602083526020830190612e53565b34610dc7576020600319360112610dc75760043567ffffffffffffffff8111610dc7576120a9903690600401612e25565b50507f81f35766bfb459eee5195947675af325872ddcb047cc8eea07597137a43dba175460ff8160081c16805f146123e057303b15155b6123b85715908161236a575b507ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460ff8160401c16159067ffffffffffffffff811680159081612362575b6001149081612358575b15908161234f575b50612327578160017fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000008316177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00556122d2575b507f25ce4ad5000000000000000000000000000000000000000000000000000000005f527fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d4216020527f068ad2b3d244cfb331455d41a4346fa1155f72ee85e27f1144f86dd0b4413549805460ff1916600117905561223c575b61221057005b7f81f35766bfb459eee5195947675af325872ddcb047cc8eea07597137a43dba17805461ff0019169055005b7fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054167ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a161220a565b7fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000001668010000000000000001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005582612191565b7ff92ee8a9000000000000000000000000000000000000000000000000000000005f5260045ffd5b9050158461213e565b303b159150612136565b83915061212c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016610101177f81f35766bfb459eee5195947675af325872ddcb047cc8eea07597137a43dba1755816120ec565b7f0dc149f0000000000000000000000000000000000000000000000000000000005f5260045ffd5b60ff82166120e0565b6060600319360112610dc7576004356006811015610dc75760243567ffffffffffffffff8111610dc757612421903690600401612e25565b9060443567ffffffffffffffff8111610dc757612442903690600401612e25565b61244d939193613310565b612455613363565b5f936001600160a01b037fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d4395460081c16916040517f72607537000000000000000000000000000000000000000000000000000000008152602081600481875afa908115611966575f91612b00575b506040517f697bc61e00000000000000000000000000000000000000000000000000000000815263ffffffff9091166004820152306024820152925f9084908180604481015b03915afa908115611966575f935f92612ae1575b508151612554575b60208760017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055604051908152f35b9091929394955060ff7fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d43f5460081c16612ab957604051927f01e1d114000000000000000000000000000000000000000000000000000000008452602084600481305afa938415611966575f94612a85575b50604051946125d386612e78565b338652602086019267ffffffffffffffff4216845260408701976125f78b8a61312b565b6126008161301a565b9961260e6040519b8c612eb0565b818b523682820111610dc757815f92602092838e01378b0101526060870198895260808701945f865260a088019a5f8c5260c089019788526001600160a01b036126566133da565b16906040805180937f55fdf55a0000000000000000000000000000000000000000000000000000000082528180612693898c8c8b600486016130f3565b03915afa918215611966575f92612a46575b506004146129e8575b509061270d6080939261273161271f966001600160a01b036126ce6133da565b1694604051988997889687967f09e14bb70000000000000000000000000000000000000000000000000000000088528b6004890152608488019061305e565b9060031987830301602488015261309a565b916003198584030160448601526130d3565b336064830152039134905af1908115611966575f91612969575b505194855f527fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d4406020526001600160a01b0360405f209551167bffffffffffffffff00000000000000000000000000000000000000008654935160a01b1691516006811015611d63577cff000000000000000000000000000000000000000000000000000000007fffffff00000000000000000000000000000000000000000000000000000000009160e01b16931617171783556001830194519586519567ffffffffffffffff8711612955576128228154613137565b97601f8911612910575b602098508890601f89116001146128ab5797809160039798995f926128a0575b50505f198260011b92881b1c19161790555b61287c6002860192511515839060ff60ff1983541691151516179055565b51815461ff00191690151560081b61ff001617905551910155828080808080612525565b015190508a8061284c565b90601f19891691835f52815f20925f5b8181106128f9575091600193918b60039a9b9c94106128e2575b505050811b01905561285e565b01515f1960f8848b1b161c191690558a80806128d5565b92938c6001819287860151815501950193016128bb565b815f5260205f20601f890160051c81019960208a1061294b575b601f0160051c01985b898110612940575061282c565b5f8155600101612933565b909950899061292a565b634e487b7160e01b5f52604160045260245ffd5b905060803d6080116129e1575b6129808183612eb0565b810190608081830312610dc757604051916060830183811067ffffffffffffffff8211176129555760405281518352602082015167ffffffffffffffff81168103610dc75760208401526129d691604001613036565b60408201528861274b565b503d612976565b612a1090612a048c959493955160208082518301019101613260565b9392505050519061316f565b3410612a1e5790918b6126ae565b7f1a041778000000000000000000000000000000000000000000000000000000005f5260045ffd5b90915060403d604011612a7e575b612a5e8183612eb0565b810190604081830312610dc757600491612a7791613036565b91906126a5565b503d612a54565b9093506020813d602011612ab1575b81612aa160209383612eb0565b81010312610dc7575192886125c5565b3d9150612a94565b7fe7ce5391000000000000000000000000000000000000000000000000000000005f5260045ffd5b909350612af891503d805f833e6110528183612eb0565b90928861251d565b90506020813d602011612b39575b81612b1b60209383612eb0565b81010312610dc75761250993612b315f92612ed3565b9150936124c3565b3d9150612b0e565b34610dc7576020600319360112610dc7577fffffffff00000000000000000000000000000000000000000000000000000000612b7b612e16565b917f25ce4ad5000000000000000000000000000000000000000000000000000000005f527fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d42160205260405f2060ff19815416905560208101907f6163636f756e74696e6742726964676546616365742829000000000000000000825260178152612c06603782612eb0565b51902016905f5b7fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d42054808210156119645783612c62837fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d4206131dc565b90549060031b1c14612c775750600101612c0d565b9192909215612d6f575b505f198101908111612d5b57610cd3610ca5612cbd927fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d4206131dc565b90557fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d420548015612d47575f1901612d14817fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d4206131dc565b5f1982549160031b1b191690557fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d420555f80f35b634e487b7160e01b5f52603160045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b5f80604051602081019084825260048152612d8b602482612eb0565b5190305afa90612d996131f1565b9115612deb575060208151918180820193849201010312610dc75751620186a0811115612c81577f67e7be8f000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b7f712f7784000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b600435908115158203610dc757565b9181601f84011215610dc75782359167ffffffffffffffff8311610dc75760208381860195010111610dc757565b90601f19601f602080948051918291828752018686015e5f8582860101520116010190565b60e0810190811067ffffffffffffffff82111761295557604052565b6040810190811067ffffffffffffffff82111761295557604052565b90601f601f19910116810190811067ffffffffffffffff82111761295557604052565b519063ffffffff82168203610dc757565b67ffffffffffffffff81116129555760051b60200190565b51906001600160a01b0382168203610dc757565b9080601f83011215610dc7578151612f2781612ee4565b92612f356040519485612eb0565b81845260208085019260051b820101928311610dc757602001905b828210612f5d5750505090565b60208091612f6a84612efc565b815201910190612f50565b919091604081840312610dc757805167ffffffffffffffff8111610dc757810183601f82011215610dc757805190612fac82612ee4565b91612fba6040519384612eb0565b80835260208084019160051b83010191868311610dc757602001905b8282106130025750505092602082015167ffffffffffffffff8111610dc757612fff9201612f10565b90565b6020809161300f84612ed3565b815201910190612fd6565b67ffffffffffffffff811161295557601f01601f191660200190565b9190826040910312610dc75760405161304e81612e94565b6020808294805184520151910152565b90602080835192838152019201905f5b81811061307b5750505090565b82516001600160a01b031684526020938401939092019160010161306e565b90602080835192838152019201905f5b8181106130b75750505090565b825163ffffffff168452602093840193909201916001016130aa565b601f8260209493601f1993818652868601375f8582860101520116010190565b9290612fff949261310f61311d9260608752606087019061305e565b90858203602087015261309a565b9260408185039101526130d3565b6006821015611d635752565b90600182811c92168015613165575b602083101461315157565b634e487b7160e01b5f52602260045260245ffd5b91607f1691613146565b91908201809211612d5b57565b90816020910312610dc757516001600160a01b0381168103610dc75790565b80518210156131af5760209160051b010190565b634e487b7160e01b5f52603260045260245ffd5b51906bffffffffffffffffffffffff82168203610dc757565b80548210156131af575f5260205f2001905f90565b3d1561321b573d906132028261301a565b916132106040519384612eb0565b82523d5f602084013e565b606090565b90816060910312610dc757805191612fff604061323f60208501612efc565b9301612efc565b9190826040910312610dc757612fff602083519301612efc565b919091608081840312610dc757805167ffffffffffffffff8111610dc7578361328a918301612f10565b92602082015167ffffffffffffffff8111610dc75782019080601f83011215610dc75781516132b881612ee4565b926132c66040519485612eb0565b81845260208085019260051b820101928311610dc757602001905b828210613300575050509160606132fa60408401612efc565b92015190565b81518152602091820191016132e1565b60ff7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300541661333b57565b7fd93c0665000000000000000000000000000000000000000000000000000000005f5260045ffd5b60027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0054146133b25760027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b7f3ee5aeb5000000000000000000000000000000000000000000000000000000005f5260045ffd5b6001600160a01b037fd09b734b71bdcd746b12ab72e4d522baa759b39b22882c56e4d58c24ee36d43f5460101c1680156134115790565b50600460206001600160a01b037fb1f8eb8d5f5694fe92802e1062618177031a72ddac422b154aa1cc0abdb48a345416604051928380927f363a20940000000000000000000000000000000000000000000000000000000082525afa908115611966575f9161347e575090565b90506020813d6020116134aa575b8161349960209383612eb0565b81010312610dc757612fff90612efc565b3d915061348c565b90915f198383099280830292838086109503948086039514613543578483111561352b5790829109815f0382168092046002816003021880820260020302808202600203028082026002030280820260020302808202600203028091026002030293600183805f03040190848311900302920304170290565b82634e487b715f52156003026011186020526024601cfd5b505080925015613551570490565b634e487b7160e01b5f52601260045260245ffdfea264697066735822122018dceca79aaa649a4dcc0816c12941568d4a5fcbcc78d04ca18be1cbfc5dad4b64736f6c634300081c0033

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]

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.