creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "@layerzerolabs/solidity-examples/contracts/interfaces/ILayerZeroEndpoint.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n    // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n    // @param _dstChainId - the destination chain identifier\n    // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n    // @param _payload - a custom bytes payload to send to the destination contract\n    // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n    // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n    // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n    function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n    // @notice used by the messaging library to publish verified payload\n    // @param _srcChainId - the source chain identifier\n    // @param _srcAddress - the source contract (as bytes) at the source chain\n    // @param _dstAddress - the address on destination chain\n    // @param _nonce - the unbound message ordering nonce\n    // @param _gasLimit - the gas limit for external contract execution\n    // @param _payload - verified payload to send to the destination contract\n    function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n    // @notice get the inboundNonce of a lzApp from a source chain which could be EVM or non-EVM chain\n    // @param _srcChainId - the source chain identifier\n    // @param _srcAddress - the source chain contract address\n    function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n    // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n    // @param _srcAddress - the source chain contract address\n    function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n    // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n    // @param _dstChainId - the destination chain identifier\n    // @param _userApplication - the user app address on this EVM chain\n    // @param _payload - the custom message to send over LayerZero\n    // @param _payInZRO - if false, user app pays the protocol fee in native token\n    // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n    function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n    // @notice get this Endpoint's immutable source identifier\n    function getChainId() external view returns (uint16);\n\n    // @notice the interface to retry failed message on this Endpoint destination\n    // @param _srcChainId - the source chain identifier\n    // @param _srcAddress - the source chain contract address\n    // @param _payload - the payload to be retried\n    function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n    // @notice query if any STORED payload (message blocking) at the endpoint.\n    // @param _srcChainId - the source chain identifier\n    // @param _srcAddress - the source chain contract address\n    function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n    // @notice query if the _libraryAddress is valid for sending msgs.\n    // @param _userApplication - the user app address on this EVM chain\n    function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n    // @notice query if the _libraryAddress is valid for receiving msgs.\n    // @param _userApplication - the user app address on this EVM chain\n    function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n    // @notice query if the non-reentrancy guard for send() is on\n    // @return true if the guard is on. false otherwise\n    function isSendingPayload() external view returns (bool);\n\n    // @notice query if the non-reentrancy guard for receive() is on\n    // @return true if the guard is on. false otherwise\n    function isReceivingPayload() external view returns (bool);\n\n    // @notice get the configuration of the LayerZero messaging library of the specified version\n    // @param _version - messaging library version\n    // @param _chainId - the chainId for the pending config change\n    // @param _userApplication - the contract address of the user application\n    // @param _configType - type of configuration. every messaging library has its own convention.\n    function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n    // @notice get the send() LayerZero messaging library version\n    // @param _userApplication - the contract address of the user application\n    function getSendVersion(address _userApplication) external view returns (uint16);\n\n    // @notice get the lzReceive() LayerZero messaging library version\n    // @param _userApplication - the contract address of the user application\n    function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n"
      },
      "@layerzerolabs/solidity-examples/contracts/interfaces/ILayerZeroReceiver.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n    // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n    // @param _srcChainId - the source endpoint identifier\n    // @param _srcAddress - the source sending contract address from the source chain\n    // @param _nonce - the ordered message nonce\n    // @param _payload - the signed payload is the UA bytes has encoded to be sent\n    function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n"
      },
      "@layerzerolabs/solidity-examples/contracts/interfaces/ILayerZeroUserApplicationConfig.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n    // @notice set the configuration of the LayerZero messaging library of the specified version\n    // @param _version - messaging library version\n    // @param _chainId - the chainId for the pending config change\n    // @param _configType - type of configuration. every messaging library has its own convention.\n    // @param _config - configuration in the bytes. can encode arbitrary content.\n    function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n    // @notice set the send() LayerZero messaging library version to _version\n    // @param _version - new messaging library version\n    function setSendVersion(uint16 _version) external;\n\n    // @notice set the lzReceive() LayerZero messaging library version to _version\n    // @param _version - new messaging library version\n    function setReceiveVersion(uint16 _version) external;\n\n    // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n    // @param _srcChainId - the chainId of the source chain\n    // @param _srcAddress - the contract address of the source contract at the source chain\n    function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n"
      },
      "@layerzerolabs/solidity-examples/contracts/interfaces/IStargateReceiver.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.4;\n\ninterface IStargateReceiver {\n    function sgReceive(\n        uint16 _chainId,\n        bytes memory _srcAddress,\n        uint256 _nonce,\n        address _token,\n        uint256 amountLD,\n        bytes memory payload\n    ) external;\n}\n"
      },
      "@layerzerolabs/solidity-examples/contracts/interfaces/IStargateRouter.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.4;\npragma abicoder v2;\n\ninterface IStargateRouter {\n    struct lzTxObj {\n        uint256 dstGasForCall;\n        uint256 dstNativeAmount;\n        bytes dstNativeAddr;\n    }\n\n    function addLiquidity(\n        uint256 _poolId,\n        uint256 _amountLD,\n        address _to\n    ) external;\n\n    function swap(\n        uint16 _dstChainId,\n        uint256 _srcPoolId,\n        uint256 _dstPoolId,\n        address payable _refundAddress,\n        uint256 _amountLD,\n        uint256 _minAmountLD,\n        lzTxObj memory _lzTxParams,\n        bytes calldata _to,\n        bytes calldata _payload\n    ) external payable;\n\n    function redeemRemote(\n        uint16 _dstChainId,\n        uint256 _srcPoolId,\n        uint256 _dstPoolId,\n        address payable _refundAddress,\n        uint256 _amountLP,\n        uint256 _minAmountLD,\n        bytes calldata _to,\n        lzTxObj memory _lzTxParams\n    ) external payable;\n\n    function instantRedeemLocal(\n        uint16 _srcPoolId,\n        uint256 _amountLP,\n        address _to\n    ) external returns (uint256);\n\n    function redeemLocal(\n        uint16 _dstChainId,\n        uint256 _srcPoolId,\n        uint256 _dstPoolId,\n        address payable _refundAddress,\n        uint256 _amountLP,\n        bytes calldata _to,\n        lzTxObj memory _lzTxParams\n    ) external payable;\n\n    function sendCredits(\n        uint16 _dstChainId,\n        uint256 _srcPoolId,\n        uint256 _dstPoolId,\n        address payable _refundAddress\n    ) external payable;\n\n    function quoteLayerZeroFee(\n        uint16 _dstChainId,\n        uint8 _functionType,\n        bytes calldata _toAddress,\n        bytes calldata _transferAndCallPayload,\n        lzTxObj memory _lzTxParams\n    ) external view returns (uint256, uint256);\n}\n"
      },
      "@solidstate/contracts/access/ownable/IOwnable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { IERC173 } from '../../interfaces/IERC173.sol';\nimport { IOwnableInternal } from './IOwnableInternal.sol';\n\ninterface IOwnable is IOwnableInternal, IERC173 {}\n"
      },
      "@solidstate/contracts/access/ownable/IOwnableInternal.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { IERC173Internal } from '../../interfaces/IERC173Internal.sol';\n\ninterface IOwnableInternal is IERC173Internal {\n    error Ownable__NotOwner();\n    error Ownable__NotTransitiveOwner();\n}\n"
      },
      "@solidstate/contracts/access/ownable/ISafeOwnable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { IOwnable } from './IOwnable.sol';\nimport { ISafeOwnableInternal } from './ISafeOwnableInternal.sol';\n\ninterface ISafeOwnable is ISafeOwnableInternal, IOwnable {\n    /**\n     * @notice get the nominated owner who has permission to call acceptOwnership\n     */\n    function nomineeOwner() external view returns (address);\n\n    /**\n     * @notice accept transfer of contract ownership\n     */\n    function acceptOwnership() external;\n}\n"
      },
      "@solidstate/contracts/access/ownable/ISafeOwnableInternal.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { IOwnableInternal } from './IOwnableInternal.sol';\n\ninterface ISafeOwnableInternal is IOwnableInternal {\n    error SafeOwnable__NotNomineeOwner();\n}\n"
      },
      "@solidstate/contracts/access/ownable/Ownable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { IERC173 } from '../../interfaces/IERC173.sol';\nimport { IOwnable } from './IOwnable.sol';\nimport { OwnableInternal } from './OwnableInternal.sol';\n\n/**\n * @title Ownership access control based on ERC173\n */\nabstract contract Ownable is IOwnable, OwnableInternal {\n    /**\n     * @inheritdoc IERC173\n     */\n    function owner() public view virtual returns (address) {\n        return _owner();\n    }\n\n    /**\n     * @inheritdoc IERC173\n     */\n    function transferOwnership(address account) public virtual onlyOwner {\n        _transferOwnership(account);\n    }\n}\n"
      },
      "@solidstate/contracts/access/ownable/OwnableInternal.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { IERC173 } from '../../interfaces/IERC173.sol';\nimport { AddressUtils } from '../../utils/AddressUtils.sol';\nimport { IOwnableInternal } from './IOwnableInternal.sol';\nimport { OwnableStorage } from './OwnableStorage.sol';\n\nabstract contract OwnableInternal is IOwnableInternal {\n    using AddressUtils for address;\n\n    modifier onlyOwner() {\n        if (msg.sender != _owner()) revert Ownable__NotOwner();\n        _;\n    }\n\n    modifier onlyTransitiveOwner() {\n        if (msg.sender != _transitiveOwner())\n            revert Ownable__NotTransitiveOwner();\n        _;\n    }\n\n    function _owner() internal view virtual returns (address) {\n        return OwnableStorage.layout().owner;\n    }\n\n    function _transitiveOwner() internal view virtual returns (address owner) {\n        owner = _owner();\n\n        while (owner.isContract()) {\n            try IERC173(owner).owner() returns (address transitiveOwner) {\n                owner = transitiveOwner;\n            } catch {\n                break;\n            }\n        }\n    }\n\n    function _transferOwnership(address account) internal virtual {\n        _setOwner(account);\n    }\n\n    function _setOwner(address account) internal virtual {\n        OwnableStorage.Layout storage l = OwnableStorage.layout();\n        emit OwnershipTransferred(l.owner, account);\n        l.owner = account;\n    }\n}\n"
      },
      "@solidstate/contracts/access/ownable/OwnableStorage.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nlibrary OwnableStorage {\n    struct Layout {\n        address owner;\n    }\n\n    bytes32 internal constant STORAGE_SLOT =\n        keccak256('solidstate.contracts.storage.Ownable');\n\n    function layout() internal pure returns (Layout storage l) {\n        bytes32 slot = STORAGE_SLOT;\n        assembly {\n            l.slot := slot\n        }\n    }\n}\n"
      },
      "@solidstate/contracts/access/ownable/SafeOwnable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { Ownable } from './Ownable.sol';\nimport { ISafeOwnable } from './ISafeOwnable.sol';\nimport { OwnableInternal } from './OwnableInternal.sol';\nimport { SafeOwnableInternal } from './SafeOwnableInternal.sol';\n\n/**\n * @title Ownership access control based on ERC173 with ownership transfer safety check\n */\nabstract contract SafeOwnable is ISafeOwnable, Ownable, SafeOwnableInternal {\n    /**\n     * @inheritdoc ISafeOwnable\n     */\n    function nomineeOwner() public view virtual returns (address) {\n        return _nomineeOwner();\n    }\n\n    /**\n     * @inheritdoc ISafeOwnable\n     */\n    function acceptOwnership() public virtual onlyNomineeOwner {\n        _acceptOwnership();\n    }\n\n    function _transferOwnership(\n        address account\n    ) internal virtual override(OwnableInternal, SafeOwnableInternal) {\n        super._transferOwnership(account);\n    }\n}\n"
      },
      "@solidstate/contracts/access/ownable/SafeOwnableInternal.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { ISafeOwnableInternal } from './ISafeOwnableInternal.sol';\nimport { OwnableInternal } from './OwnableInternal.sol';\nimport { SafeOwnableStorage } from './SafeOwnableStorage.sol';\n\nabstract contract SafeOwnableInternal is ISafeOwnableInternal, OwnableInternal {\n    modifier onlyNomineeOwner() {\n        if (msg.sender != _nomineeOwner())\n            revert SafeOwnable__NotNomineeOwner();\n        _;\n    }\n\n    /**\n     * @notice get the nominated owner who has permission to call acceptOwnership\n     */\n    function _nomineeOwner() internal view virtual returns (address) {\n        return SafeOwnableStorage.layout().nomineeOwner;\n    }\n\n    /**\n     * @notice accept transfer of contract ownership\n     */\n    function _acceptOwnership() internal virtual {\n        _setOwner(msg.sender);\n        delete SafeOwnableStorage.layout().nomineeOwner;\n    }\n\n    /**\n     * @notice grant permission to given address to claim contract ownership\n     */\n    function _transferOwnership(address account) internal virtual override {\n        _setNomineeOwner(account);\n    }\n\n    /**\n     * @notice set nominee owner\n     */\n    function _setNomineeOwner(address account) internal virtual {\n        SafeOwnableStorage.layout().nomineeOwner = account;\n    }\n}\n"
      },
      "@solidstate/contracts/access/ownable/SafeOwnableStorage.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nlibrary SafeOwnableStorage {\n    struct Layout {\n        address nomineeOwner;\n    }\n\n    bytes32 internal constant STORAGE_SLOT =\n        keccak256('solidstate.contracts.storage.SafeOwnable');\n\n    function layout() internal pure returns (Layout storage l) {\n        bytes32 slot = STORAGE_SLOT;\n        assembly {\n            l.slot := slot\n        }\n    }\n}\n"
      },
      "@solidstate/contracts/cryptography/ECDSA.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\n/**\n * @title Elliptic Curve Digital Signature Algorithm (ECDSA) operations\n * @dev derived from https://github.com/OpenZeppelin/openzeppelin-contracts (MIT license)\n */\nlibrary ECDSA {\n    error ECDSA__InvalidS();\n    error ECDSA__InvalidSignature();\n    error ECDSA__InvalidSignatureLength();\n    error ECDSA__InvalidV();\n\n    /**\n     * @notice recover signer of hashed message from signature\n     * @param hash hashed data payload\n     * @param signature signed data payload\n     * @return recovered message signer\n     */\n    function recover(\n        bytes32 hash,\n        bytes memory signature\n    ) internal pure returns (address) {\n        if (signature.length != 65) revert ECDSA__InvalidSignatureLength();\n\n        bytes32 r;\n        bytes32 s;\n        uint8 v;\n\n        assembly {\n            r := mload(add(signature, 0x20))\n            s := mload(add(signature, 0x40))\n            v := byte(0, mload(add(signature, 0x60)))\n        }\n\n        return recover(hash, v, r, s);\n    }\n\n    /**\n     * @notice recover signer of hashed message from signature v, r, and s values\n     * @param hash hashed data payload\n     * @param v signature \"v\" value\n     * @param r signature \"r\" value\n     * @param s signature \"s\" value\n     * @return recovered message signer\n     */\n    function recover(\n        bytes32 hash,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal pure returns (address) {\n        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n        // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most\n        // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n        //\n        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n        // these malleable signatures as well.\n        if (\n            uint256(s) >\n            0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0\n        ) revert ECDSA__InvalidS();\n        if (v != 27 && v != 28) revert ECDSA__InvalidV();\n\n        // If the signature is valid (and not malleable), return the signer address\n        address signer = ecrecover(hash, v, r, s);\n        if (signer == address(0)) revert ECDSA__InvalidSignature();\n\n        return signer;\n    }\n\n    /**\n     * @notice generate an \"Ethereum Signed Message\" in the format returned by the eth_sign JSON-RPC method\n     * @param hash hashed data payload\n     * @return signed message hash\n     */\n    function toEthSignedMessageHash(\n        bytes32 hash\n    ) internal pure returns (bytes32) {\n        return\n            keccak256(\n                abi.encodePacked('\\x19Ethereum Signed Message:\\n32', hash)\n            );\n    }\n}\n"
      },
      "@solidstate/contracts/cryptography/EIP712.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @title EIP-712 typed structured data hashing and signing\n * @dev see https://eips.ethereum.org/EIPS/eip-712\n */\nlibrary EIP712 {\n    bytes32 internal constant EIP712_TYPE_HASH =\n        keccak256(\n            'EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'\n        );\n\n    /**\n     * @notice calculate unique EIP-712 domain separator\n     * @dev name and version inputs are hashed as required by EIP-712 because they are of dynamic-length types\n     * @dev implementation of EIP712Domain struct type excludes the optional salt parameter\n     * @param nameHash hash of human-readable signing domain name\n     * @param versionHash hash of signing domain version\n     * @return domainSeparator domain separator\n     */\n    function calculateDomainSeparator(\n        bytes32 nameHash,\n        bytes32 versionHash\n    ) internal view returns (bytes32 domainSeparator) {\n        // execute EIP-712 hashStruct procedure using assembly, equavalent to:\n        //\n        // domainSeparator = keccak256(\n        //   abi.encode(\n        //     EIP712_TYPE_HASH,\n        //     nameHash,\n        //     versionHash,\n        //     block.chainid,\n        //     address(this)\n        //   )\n        // );\n\n        bytes32 typeHash = EIP712_TYPE_HASH;\n\n        assembly {\n            // load free memory pointer\n            let pointer := mload(64)\n\n            mstore(pointer, typeHash)\n            mstore(add(pointer, 32), nameHash)\n            mstore(add(pointer, 64), versionHash)\n            mstore(add(pointer, 96), chainid())\n            mstore(add(pointer, 128), address())\n\n            domainSeparator := keccak256(pointer, 160)\n        }\n    }\n}\n"
      },
      "@solidstate/contracts/data/EnumerableMap.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\n/**\n * @title Map implementation with enumeration functions\n * @dev derived from https://github.com/OpenZeppelin/openzeppelin-contracts (MIT license)\n */\nlibrary EnumerableMap {\n    error EnumerableMap__IndexOutOfBounds();\n    error EnumerableMap__NonExistentKey();\n\n    struct MapEntry {\n        bytes32 _key;\n        bytes32 _value;\n    }\n\n    struct Map {\n        MapEntry[] _entries;\n        // 1-indexed to allow 0 to signify nonexistence\n        mapping(bytes32 => uint256) _indexes;\n    }\n\n    struct AddressToAddressMap {\n        Map _inner;\n    }\n\n    struct UintToAddressMap {\n        Map _inner;\n    }\n\n    function at(\n        AddressToAddressMap storage map,\n        uint256 index\n    ) internal view returns (address, address) {\n        (bytes32 key, bytes32 value) = _at(map._inner, index);\n\n        return (\n            address(uint160(uint256(key))),\n            address(uint160(uint256(value)))\n        );\n    }\n\n    function at(\n        UintToAddressMap storage map,\n        uint256 index\n    ) internal view returns (uint256, address) {\n        (bytes32 key, bytes32 value) = _at(map._inner, index);\n        return (uint256(key), address(uint160(uint256(value))));\n    }\n\n    function contains(\n        AddressToAddressMap storage map,\n        address key\n    ) internal view returns (bool) {\n        return _contains(map._inner, bytes32(uint256(uint160(key))));\n    }\n\n    function contains(\n        UintToAddressMap storage map,\n        uint256 key\n    ) internal view returns (bool) {\n        return _contains(map._inner, bytes32(key));\n    }\n\n    function length(\n        AddressToAddressMap storage map\n    ) internal view returns (uint256) {\n        return _length(map._inner);\n    }\n\n    function length(\n        UintToAddressMap storage map\n    ) internal view returns (uint256) {\n        return _length(map._inner);\n    }\n\n    function get(\n        AddressToAddressMap storage map,\n        address key\n    ) internal view returns (address) {\n        return\n            address(\n                uint160(\n                    uint256(_get(map._inner, bytes32(uint256(uint160(key)))))\n                )\n            );\n    }\n\n    function get(\n        UintToAddressMap storage map,\n        uint256 key\n    ) internal view returns (address) {\n        return address(uint160(uint256(_get(map._inner, bytes32(key)))));\n    }\n\n    function set(\n        AddressToAddressMap storage map,\n        address key,\n        address value\n    ) internal returns (bool) {\n        return\n            _set(\n                map._inner,\n                bytes32(uint256(uint160(key))),\n                bytes32(uint256(uint160(value)))\n            );\n    }\n\n    function set(\n        UintToAddressMap storage map,\n        uint256 key,\n        address value\n    ) internal returns (bool) {\n        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));\n    }\n\n    function remove(\n        AddressToAddressMap storage map,\n        address key\n    ) internal returns (bool) {\n        return _remove(map._inner, bytes32(uint256(uint160(key))));\n    }\n\n    function remove(\n        UintToAddressMap storage map,\n        uint256 key\n    ) internal returns (bool) {\n        return _remove(map._inner, bytes32(key));\n    }\n\n    function toArray(\n        AddressToAddressMap storage map\n    )\n        internal\n        view\n        returns (address[] memory keysOut, address[] memory valuesOut)\n    {\n        uint256 len = map._inner._entries.length;\n\n        keysOut = new address[](len);\n        valuesOut = new address[](len);\n\n        unchecked {\n            for (uint256 i; i < len; ++i) {\n                keysOut[i] = address(\n                    uint160(uint256(map._inner._entries[i]._key))\n                );\n                valuesOut[i] = address(\n                    uint160(uint256(map._inner._entries[i]._value))\n                );\n            }\n        }\n    }\n\n    function toArray(\n        UintToAddressMap storage map\n    )\n        internal\n        view\n        returns (uint256[] memory keysOut, address[] memory valuesOut)\n    {\n        uint256 len = map._inner._entries.length;\n\n        keysOut = new uint256[](len);\n        valuesOut = new address[](len);\n\n        unchecked {\n            for (uint256 i; i < len; ++i) {\n                keysOut[i] = uint256(map._inner._entries[i]._key);\n                valuesOut[i] = address(\n                    uint160(uint256(map._inner._entries[i]._value))\n                );\n            }\n        }\n    }\n\n    function keys(\n        AddressToAddressMap storage map\n    ) internal view returns (address[] memory keysOut) {\n        uint256 len = map._inner._entries.length;\n\n        keysOut = new address[](len);\n\n        unchecked {\n            for (uint256 i; i < len; ++i) {\n                keysOut[i] = address(\n                    uint160(uint256(map._inner._entries[i]._key))\n                );\n            }\n        }\n    }\n\n    function keys(\n        UintToAddressMap storage map\n    ) internal view returns (uint256[] memory keysOut) {\n        uint256 len = map._inner._entries.length;\n\n        keysOut = new uint256[](len);\n\n        unchecked {\n            for (uint256 i; i < len; ++i) {\n                keysOut[i] = uint256(map._inner._entries[i]._key);\n            }\n        }\n    }\n\n    function values(\n        AddressToAddressMap storage map\n    ) internal view returns (address[] memory valuesOut) {\n        uint256 len = map._inner._entries.length;\n\n        valuesOut = new address[](len);\n\n        unchecked {\n            for (uint256 i; i < len; ++i) {\n                valuesOut[i] = address(\n                    uint160(uint256(map._inner._entries[i]._value))\n                );\n            }\n        }\n    }\n\n    function values(\n        UintToAddressMap storage map\n    ) internal view returns (address[] memory valuesOut) {\n        uint256 len = map._inner._entries.length;\n\n        valuesOut = new address[](len);\n\n        unchecked {\n            for (uint256 i; i < len; ++i) {\n                valuesOut[i] = address(\n                    uint160(uint256(map._inner._entries[i]._value))\n                );\n            }\n        }\n    }\n\n    function _at(\n        Map storage map,\n        uint256 index\n    ) private view returns (bytes32, bytes32) {\n        if (index >= map._entries.length)\n            revert EnumerableMap__IndexOutOfBounds();\n\n        MapEntry storage entry = map._entries[index];\n        return (entry._key, entry._value);\n    }\n\n    function _contains(\n        Map storage map,\n        bytes32 key\n    ) private view returns (bool) {\n        return map._indexes[key] != 0;\n    }\n\n    function _length(Map storage map) private view returns (uint256) {\n        return map._entries.length;\n    }\n\n    function _get(Map storage map, bytes32 key) private view returns (bytes32) {\n        uint256 keyIndex = map._indexes[key];\n        if (keyIndex == 0) revert EnumerableMap__NonExistentKey();\n        unchecked {\n            return map._entries[keyIndex - 1]._value;\n        }\n    }\n\n    function _set(\n        Map storage map,\n        bytes32 key,\n        bytes32 value\n    ) private returns (bool) {\n        uint256 keyIndex = map._indexes[key];\n\n        if (keyIndex == 0) {\n            map._entries.push(MapEntry({ _key: key, _value: value }));\n            map._indexes[key] = map._entries.length;\n            return true;\n        } else {\n            unchecked {\n                map._entries[keyIndex - 1]._value = value;\n            }\n            return false;\n        }\n    }\n\n    function _remove(Map storage map, bytes32 key) private returns (bool) {\n        uint256 keyIndex = map._indexes[key];\n\n        if (keyIndex != 0) {\n            unchecked {\n                MapEntry storage last = map._entries[map._entries.length - 1];\n\n                // move last entry to now-vacant index\n                map._entries[keyIndex - 1] = last;\n                map._indexes[last._key] = keyIndex;\n            }\n\n            // clear last index\n            map._entries.pop();\n            delete map._indexes[key];\n\n            return true;\n        } else {\n            return false;\n        }\n    }\n}\n"
      },
      "@solidstate/contracts/data/EnumerableSet.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\n/**\n * @title Set implementation with enumeration functions\n * @dev derived from https://github.com/OpenZeppelin/openzeppelin-contracts (MIT license)\n */\nlibrary EnumerableSet {\n    error EnumerableSet__IndexOutOfBounds();\n\n    struct Set {\n        bytes32[] _values;\n        // 1-indexed to allow 0 to signify nonexistence\n        mapping(bytes32 => uint256) _indexes;\n    }\n\n    struct Bytes32Set {\n        Set _inner;\n    }\n\n    struct AddressSet {\n        Set _inner;\n    }\n\n    struct UintSet {\n        Set _inner;\n    }\n\n    function at(\n        Bytes32Set storage set,\n        uint256 index\n    ) internal view returns (bytes32) {\n        return _at(set._inner, index);\n    }\n\n    function at(\n        AddressSet storage set,\n        uint256 index\n    ) internal view returns (address) {\n        return address(uint160(uint256(_at(set._inner, index))));\n    }\n\n    function at(\n        UintSet storage set,\n        uint256 index\n    ) internal view returns (uint256) {\n        return uint256(_at(set._inner, index));\n    }\n\n    function contains(\n        Bytes32Set storage set,\n        bytes32 value\n    ) internal view returns (bool) {\n        return _contains(set._inner, value);\n    }\n\n    function contains(\n        AddressSet storage set,\n        address value\n    ) internal view returns (bool) {\n        return _contains(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    function contains(\n        UintSet storage set,\n        uint256 value\n    ) internal view returns (bool) {\n        return _contains(set._inner, bytes32(value));\n    }\n\n    function indexOf(\n        Bytes32Set storage set,\n        bytes32 value\n    ) internal view returns (uint256) {\n        return _indexOf(set._inner, value);\n    }\n\n    function indexOf(\n        AddressSet storage set,\n        address value\n    ) internal view returns (uint256) {\n        return _indexOf(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    function indexOf(\n        UintSet storage set,\n        uint256 value\n    ) internal view returns (uint256) {\n        return _indexOf(set._inner, bytes32(value));\n    }\n\n    function length(Bytes32Set storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n    function length(AddressSet storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n    function length(UintSet storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n    function add(\n        Bytes32Set storage set,\n        bytes32 value\n    ) internal returns (bool) {\n        return _add(set._inner, value);\n    }\n\n    function add(\n        AddressSet storage set,\n        address value\n    ) internal returns (bool) {\n        return _add(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    function add(UintSet storage set, uint256 value) internal returns (bool) {\n        return _add(set._inner, bytes32(value));\n    }\n\n    function remove(\n        Bytes32Set storage set,\n        bytes32 value\n    ) internal returns (bool) {\n        return _remove(set._inner, value);\n    }\n\n    function remove(\n        AddressSet storage set,\n        address value\n    ) internal returns (bool) {\n        return _remove(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    function remove(\n        UintSet storage set,\n        uint256 value\n    ) internal returns (bool) {\n        return _remove(set._inner, bytes32(value));\n    }\n\n    function toArray(\n        Bytes32Set storage set\n    ) internal view returns (bytes32[] memory) {\n        return set._inner._values;\n    }\n\n    function toArray(\n        AddressSet storage set\n    ) internal view returns (address[] memory) {\n        bytes32[] storage values = set._inner._values;\n        address[] storage array;\n\n        assembly {\n            array.slot := values.slot\n        }\n\n        return array;\n    }\n\n    function toArray(\n        UintSet storage set\n    ) internal view returns (uint256[] memory) {\n        bytes32[] storage values = set._inner._values;\n        uint256[] storage array;\n\n        assembly {\n            array.slot := values.slot\n        }\n\n        return array;\n    }\n\n    function _at(\n        Set storage set,\n        uint256 index\n    ) private view returns (bytes32) {\n        if (index >= set._values.length)\n            revert EnumerableSet__IndexOutOfBounds();\n        return set._values[index];\n    }\n\n    function _contains(\n        Set storage set,\n        bytes32 value\n    ) private view returns (bool) {\n        return set._indexes[value] != 0;\n    }\n\n    function _indexOf(\n        Set storage set,\n        bytes32 value\n    ) private view returns (uint256) {\n        unchecked {\n            return set._indexes[value] - 1;\n        }\n    }\n\n    function _length(Set storage set) private view returns (uint256) {\n        return set._values.length;\n    }\n\n    function _add(\n        Set storage set,\n        bytes32 value\n    ) private returns (bool status) {\n        if (!_contains(set, value)) {\n            set._values.push(value);\n            set._indexes[value] = set._values.length;\n            status = true;\n        }\n    }\n\n    function _remove(\n        Set storage set,\n        bytes32 value\n    ) private returns (bool status) {\n        uint256 valueIndex = set._indexes[value];\n\n        if (valueIndex != 0) {\n            unchecked {\n                bytes32 last = set._values[set._values.length - 1];\n\n                // move last value to now-vacant index\n\n                set._values[valueIndex - 1] = last;\n                set._indexes[last] = valueIndex;\n            }\n            // clear last index\n\n            set._values.pop();\n            delete set._indexes[value];\n\n            status = true;\n        }\n    }\n}\n"
      },
      "@solidstate/contracts/interfaces/IERC165.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { IERC165Internal } from './IERC165Internal.sol';\n\n/**\n * @title ERC165 interface registration interface\n * @dev see https://eips.ethereum.org/EIPS/eip-165\n */\ninterface IERC165 is IERC165Internal {\n    /**\n     * @notice query whether contract has registered support for given interface\n     * @param interfaceId interface id\n     * @return bool whether interface is supported\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"
      },
      "@solidstate/contracts/interfaces/IERC165Internal.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\n/**\n * @title ERC165 interface registration interface\n */\ninterface IERC165Internal {\n\n}\n"
      },
      "@solidstate/contracts/interfaces/IERC173.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { IERC173Internal } from './IERC173Internal.sol';\n\n/**\n * @title Contract ownership standard interface\n * @dev see https://eips.ethereum.org/EIPS/eip-173\n */\ninterface IERC173 is IERC173Internal {\n    /**\n     * @notice get the ERC173 contract owner\n     * @return contract owner\n     */\n    function owner() external view returns (address);\n\n    /**\n     * @notice transfer contract ownership to new account\n     * @param account address of new owner\n     */\n    function transferOwnership(address account) external;\n}\n"
      },
      "@solidstate/contracts/interfaces/IERC173Internal.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\n/**\n * @title Partial ERC173 interface needed by internal functions\n */\ninterface IERC173Internal {\n    event OwnershipTransferred(\n        address indexed previousOwner,\n        address indexed newOwner\n    );\n}\n"
      },
      "@solidstate/contracts/interfaces/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { IERC20Internal } from './IERC20Internal.sol';\n\n/**\n * @title ERC20 interface\n * @dev see https://eips.ethereum.org/EIPS/eip-20\n */\ninterface IERC20 is IERC20Internal {\n    /**\n     * @notice query the total minted token supply\n     * @return token supply\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @notice query the token balance of given account\n     * @param account address to query\n     * @return token balance\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @notice query the allowance granted from given holder to given spender\n     * @param holder approver of allowance\n     * @param spender recipient of allowance\n     * @return token allowance\n     */\n    function allowance(\n        address holder,\n        address spender\n    ) external view returns (uint256);\n\n    /**\n     * @notice grant approval to spender to spend tokens\n     * @dev prefer ERC20Extended functions to avoid transaction-ordering vulnerability (see https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729)\n     * @param spender recipient of allowance\n     * @param amount quantity of tokens approved for spending\n     * @return success status (always true; otherwise function should revert)\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @notice transfer tokens to given recipient\n     * @param recipient beneficiary of token transfer\n     * @param amount quantity of tokens to transfer\n     * @return success status (always true; otherwise function should revert)\n     */\n    function transfer(\n        address recipient,\n        uint256 amount\n    ) external returns (bool);\n\n    /**\n     * @notice transfer tokens to given recipient on behalf of given holder\n     * @param holder holder of tokens prior to transfer\n     * @param recipient beneficiary of token transfer\n     * @param amount quantity of tokens to transfer\n     * @return success status (always true; otherwise function should revert)\n     */\n    function transferFrom(\n        address holder,\n        address recipient,\n        uint256 amount\n    ) external returns (bool);\n}\n"
      },
      "@solidstate/contracts/interfaces/IERC20Internal.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\n/**\n * @title Partial ERC20 interface needed by internal functions\n */\ninterface IERC20Internal {\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    event Approval(\n        address indexed owner,\n        address indexed spender,\n        uint256 value\n    );\n}\n"
      },
      "@solidstate/contracts/interfaces/IERC721.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { IERC165 } from './IERC165.sol';\nimport { IERC721Internal } from './IERC721Internal.sol';\n\n/**\n * @title ERC721 interface\n * @dev see https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721 is IERC721Internal, IERC165 {\n    /**\n     * @notice query the balance of given address\n     * @return balance quantity of tokens held\n     */\n    function balanceOf(address account) external view returns (uint256 balance);\n\n    /**\n     * @notice query the owner of given token\n     * @param tokenId token to query\n     * @return owner token owner\n     */\n    function ownerOf(uint256 tokenId) external view returns (address owner);\n\n    /**\n     * @notice transfer token between given addresses, checking for ERC721Receiver implementation if applicable\n     * @param from sender of token\n     * @param to receiver of token\n     * @param tokenId token id\n     */\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 tokenId\n    ) external payable;\n\n    /**\n     * @notice transfer token between given addresses, checking for ERC721Receiver implementation if applicable\n     * @param from sender of token\n     * @param to receiver of token\n     * @param tokenId token id\n     * @param data data payload\n     */\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 tokenId,\n        bytes calldata data\n    ) external payable;\n\n    /**\n     * @notice transfer token between given addresses, without checking for ERC721Receiver implementation if applicable\n     * @param from sender of token\n     * @param to receiver of token\n     * @param tokenId token id\n     */\n    function transferFrom(\n        address from,\n        address to,\n        uint256 tokenId\n    ) external payable;\n\n    /**\n     * @notice grant approval to given account to spend token\n     * @param operator address to be approved\n     * @param tokenId token to approve\n     */\n    function approve(address operator, uint256 tokenId) external payable;\n\n    /**\n     * @notice get approval status for given token\n     * @param tokenId token to query\n     * @return operator address approved to spend token\n     */\n    function getApproved(\n        uint256 tokenId\n    ) external view returns (address operator);\n\n    /**\n     * @notice grant approval to or revoke approval from given account to spend all tokens held by sender\n     * @param operator address to be approved\n     * @param status approval status\n     */\n    function setApprovalForAll(address operator, bool status) external;\n\n    /**\n     * @notice query approval status of given operator with respect to given address\n     * @param account address to query for approval granted\n     * @param operator address to query for approval received\n     * @return status whether operator is approved to spend tokens held by account\n     */\n    function isApprovedForAll(\n        address account,\n        address operator\n    ) external view returns (bool status);\n}\n"
      },
      "@solidstate/contracts/interfaces/IERC721Internal.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\n/**\n * @title Partial ERC721 interface needed by internal functions\n */\ninterface IERC721Internal {\n    event Transfer(\n        address indexed from,\n        address indexed to,\n        uint256 indexed tokenId\n    );\n\n    event Approval(\n        address indexed owner,\n        address indexed operator,\n        uint256 indexed tokenId\n    );\n\n    event ApprovalForAll(\n        address indexed owner,\n        address indexed operator,\n        bool approved\n    );\n}\n"
      },
      "@solidstate/contracts/interfaces/IERC721Receiver.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\ninterface IERC721Receiver {\n    function onERC721Received(\n        address operator,\n        address from,\n        uint256 tokenId,\n        bytes calldata data\n    ) external returns (bytes4);\n}\n"
      },
      "@solidstate/contracts/introspection/ERC165/base/ERC165Base.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { IERC165 } from '../../../interfaces/IERC165.sol';\nimport { IERC165Base } from './IERC165Base.sol';\nimport { ERC165BaseInternal } from './ERC165BaseInternal.sol';\nimport { ERC165BaseStorage } from './ERC165BaseStorage.sol';\n\n/**\n * @title ERC165 implementation\n */\nabstract contract ERC165Base is IERC165Base, ERC165BaseInternal {\n    /**\n     * @inheritdoc IERC165\n     */\n    function supportsInterface(bytes4 interfaceId) public view returns (bool) {\n        return _supportsInterface(interfaceId);\n    }\n}\n"
      },
      "@solidstate/contracts/introspection/ERC165/base/ERC165BaseInternal.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { IERC165BaseInternal } from './IERC165BaseInternal.sol';\nimport { ERC165BaseStorage } from './ERC165BaseStorage.sol';\n\n/**\n * @title ERC165 implementation\n */\nabstract contract ERC165BaseInternal is IERC165BaseInternal {\n    /**\n     * @notice indicates whether an interface is already supported based on the interfaceId\n     * @param interfaceId id of interface to check\n     * @return bool indicating whether interface is supported\n     */\n    function _supportsInterface(\n        bytes4 interfaceId\n    ) internal view virtual returns (bool) {\n        return ERC165BaseStorage.layout().supportedInterfaces[interfaceId];\n    }\n\n    /**\n     * @notice sets status of interface support\n     * @param interfaceId id of interface to set status for\n     * @param status boolean indicating whether interface will be set as supported\n     */\n    function _setSupportsInterface(\n        bytes4 interfaceId,\n        bool status\n    ) internal virtual {\n        if (interfaceId == 0xffffffff) revert ERC165Base__InvalidInterfaceId();\n        ERC165BaseStorage.layout().supportedInterfaces[interfaceId] = status;\n    }\n}\n"
      },
      "@solidstate/contracts/introspection/ERC165/base/ERC165BaseStorage.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nlibrary ERC165BaseStorage {\n    struct Layout {\n        mapping(bytes4 => bool) supportedInterfaces;\n    }\n\n    bytes32 internal constant STORAGE_SLOT =\n        keccak256('solidstate.contracts.storage.ERC165Base');\n\n    function layout() internal pure returns (Layout storage l) {\n        bytes32 slot = STORAGE_SLOT;\n        assembly {\n            l.slot := slot\n        }\n    }\n}\n"
      },
      "@solidstate/contracts/introspection/ERC165/base/IERC165Base.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport { IERC165 } from '../../../interfaces/IERC165.sol';\nimport { IERC165BaseInternal } from './IERC165BaseInternal.sol';\n\ninterface IERC165Base is IERC165, IERC165BaseInternal {}\n"
      },
      "@solidstate/contracts/introspection/ERC165/base/IERC165BaseInternal.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport { IERC165Internal } from '../../../interfaces/IERC165Internal.sol';\n\ninterface IERC165BaseInternal is IERC165Internal {\n    error ERC165Base__InvalidInterfaceId();\n}\n"
      },
      "@solidstate/contracts/proxy/diamond/readable/IDiamondReadable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\n/**\n * @title Diamond proxy introspection interface\n * @dev see https://eips.ethereum.org/EIPS/eip-2535\n */\ninterface IDiamondReadable {\n    struct Facet {\n        address target;\n        bytes4[] selectors;\n    }\n\n    /**\n     * @notice get all facets and their selectors\n     * @return diamondFacets array of structured facet data\n     */\n    function facets() external view returns (Facet[] memory diamondFacets);\n\n    /**\n     * @notice get all selectors for given facet address\n     * @param facet address of facet to query\n     * @return selectors array of function selectors\n     */\n    function facetFunctionSelectors(\n        address facet\n    ) external view returns (bytes4[] memory selectors);\n\n    /**\n     * @notice get addresses of all facets used by diamond\n     * @return addresses array of facet addresses\n     */\n    function facetAddresses()\n        external\n        view\n        returns (address[] memory addresses);\n\n    /**\n     * @notice get the address of the facet associated with given selector\n     * @param selector function selector to query\n     * @return facet facet address (zero address if not found)\n     */\n    function facetAddress(\n        bytes4 selector\n    ) external view returns (address facet);\n}\n"
      },
      "@solidstate/contracts/proxy/IProxy.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\ninterface IProxy {\n    error Proxy__ImplementationIsNotContract();\n\n    fallback() external payable;\n}\n"
      },
      "@solidstate/contracts/proxy/Proxy.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { AddressUtils } from '../utils/AddressUtils.sol';\nimport { IProxy } from './IProxy.sol';\n\n/**\n * @title Base proxy contract\n */\nabstract contract Proxy is IProxy {\n    using AddressUtils for address;\n\n    /**\n     * @notice delegate all calls to implementation contract\n     * @dev reverts if implementation address contains no code, for compatibility with metamorphic contracts\n     * @dev memory location in use by assembly may be unsafe in other contexts\n     */\n    fallback() external payable virtual {\n        address implementation = _getImplementation();\n\n        if (!implementation.isContract())\n            revert Proxy__ImplementationIsNotContract();\n\n        assembly {\n            calldatacopy(0, 0, calldatasize())\n            let result := delegatecall(\n                gas(),\n                implementation,\n                0,\n                calldatasize(),\n                0,\n                0\n            )\n            returndatacopy(0, 0, returndatasize())\n\n            switch result\n            case 0 {\n                revert(0, returndatasize())\n            }\n            default {\n                return(0, returndatasize())\n            }\n        }\n    }\n\n    /**\n     * @notice get logic implementation address\n     * @return implementation address\n     */\n    function _getImplementation() internal virtual returns (address);\n}\n"
      },
      "@solidstate/contracts/security/pausable/IPausable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { IPausableInternal } from './IPausableInternal.sol';\n\ninterface IPausable is IPausableInternal {\n    /**\n     * @notice query whether contract is paused\n     * @return status whether contract is paused\n     */\n    function paused() external view returns (bool status);\n}\n"
      },
      "@solidstate/contracts/security/pausable/IPausableInternal.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\ninterface IPausableInternal {\n    error Pausable__Paused();\n    error Pausable__NotPaused();\n\n    event Paused(address account);\n    event Unpaused(address account);\n}\n"
      },
      "@solidstate/contracts/security/pausable/Pausable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { IPausable } from './IPausable.sol';\nimport { PausableInternal } from './PausableInternal.sol';\n\n/**\n * @title Pausable security control module.\n */\nabstract contract Pausable is IPausable, PausableInternal {\n    /**\n     * @inheritdoc IPausable\n     */\n    function paused() external view virtual returns (bool status) {\n        status = _paused();\n    }\n}\n"
      },
      "@solidstate/contracts/security/pausable/PausableInternal.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { IPausableInternal } from './IPausableInternal.sol';\nimport { PausableStorage } from './PausableStorage.sol';\n\n/**\n * @title Internal functions for Pausable security control module.\n */\nabstract contract PausableInternal is IPausableInternal {\n    modifier whenNotPaused() {\n        if (_paused()) revert Pausable__Paused();\n        _;\n    }\n\n    modifier whenPaused() {\n        if (!_paused()) revert Pausable__NotPaused();\n        _;\n    }\n\n    /**\n     * @notice query whether contract is paused\n     * @return status whether contract is paused\n     */\n    function _paused() internal view virtual returns (bool status) {\n        status = PausableStorage.layout().paused;\n    }\n\n    /**\n     * @notice Triggers paused state, when contract is unpaused.\n     */\n    function _pause() internal virtual whenNotPaused {\n        PausableStorage.layout().paused = true;\n        emit Paused(msg.sender);\n    }\n\n    /**\n     * @notice Triggers unpaused state, when contract is paused.\n     */\n    function _unpause() internal virtual whenPaused {\n        delete PausableStorage.layout().paused;\n        emit Unpaused(msg.sender);\n    }\n}\n"
      },
      "@solidstate/contracts/security/pausable/PausableStorage.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nlibrary PausableStorage {\n    struct Layout {\n        bool paused;\n    }\n\n    bytes32 internal constant STORAGE_SLOT =\n        keccak256('solidstate.contracts.storage.Pausable');\n\n    function layout() internal pure returns (Layout storage l) {\n        bytes32 slot = STORAGE_SLOT;\n        assembly {\n            l.slot := slot\n        }\n    }\n}\n"
      },
      "@solidstate/contracts/security/reentrancy_guard/IReentrancyGuard.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\ninterface IReentrancyGuard {\n    error ReentrancyGuard__ReentrantCall();\n}\n"
      },
      "@solidstate/contracts/security/reentrancy_guard/ReentrancyGuard.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { IReentrancyGuard } from './IReentrancyGuard.sol';\nimport { ReentrancyGuardStorage } from './ReentrancyGuardStorage.sol';\n\n/**\n * @title Utility contract for preventing reentrancy attacks\n */\nabstract contract ReentrancyGuard is IReentrancyGuard {\n    uint256 internal constant REENTRANCY_STATUS_LOCKED = 2;\n    uint256 internal constant REENTRANCY_STATUS_UNLOCKED = 1;\n\n    modifier nonReentrant() virtual {\n        if (_isReentrancyGuardLocked()) revert ReentrancyGuard__ReentrantCall();\n        _lockReentrancyGuard();\n        _;\n        _unlockReentrancyGuard();\n    }\n\n    /**\n     * @notice returns true if the reentrancy guard is locked, false otherwise\n     */\n    function _isReentrancyGuardLocked() internal view virtual returns (bool) {\n        return\n            ReentrancyGuardStorage.layout().status == REENTRANCY_STATUS_LOCKED;\n    }\n\n    /**\n     * @notice lock functions that use the nonReentrant modifier\n     */\n    function _lockReentrancyGuard() internal virtual {\n        ReentrancyGuardStorage.layout().status = REENTRANCY_STATUS_LOCKED;\n    }\n\n    /**\n     * @notice unlock functions that use the nonReentrant modifier\n     */\n    function _unlockReentrancyGuard() internal virtual {\n        ReentrancyGuardStorage.layout().status = REENTRANCY_STATUS_UNLOCKED;\n    }\n}\n"
      },
      "@solidstate/contracts/security/reentrancy_guard/ReentrancyGuardStorage.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nlibrary ReentrancyGuardStorage {\n    struct Layout {\n        uint256 status;\n    }\n\n    bytes32 internal constant STORAGE_SLOT =\n        keccak256('solidstate.contracts.storage.ReentrancyGuard');\n\n    function layout() internal pure returns (Layout storage l) {\n        bytes32 slot = STORAGE_SLOT;\n        assembly {\n            l.slot := slot\n        }\n    }\n}\n"
      },
      "@solidstate/contracts/token/ERC20/metadata/IERC20Metadata.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { IERC20MetadataInternal } from './IERC20MetadataInternal.sol';\n\n/**\n * @title ERC20 metadata interface\n */\ninterface IERC20Metadata is IERC20MetadataInternal {\n    /**\n     * @notice return token name\n     * @return token name\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @notice return token symbol\n     * @return token symbol\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @notice return token decimals, generally used only for display purposes\n     * @return token decimals\n     */\n    function decimals() external view returns (uint8);\n}\n"
      },
      "@solidstate/contracts/token/ERC20/metadata/IERC20MetadataInternal.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\n/**\n * @title ERC20 metadata internal interface\n */\ninterface IERC20MetadataInternal {\n\n}\n"
      },
      "@solidstate/contracts/token/ERC20/permit/IERC2612.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { IERC2612Internal } from './IERC2612Internal.sol';\n\n/**\n * @title ERC2612 interface\n * @dev see https://eips.ethereum.org/EIPS/eip-2612.\n */\ninterface IERC2612 is IERC2612Internal {\n    /**\n     * @notice return the EIP-712 domain separator unique to contract and chain\n     * @return domainSeparator domain separator\n     */\n    function DOMAIN_SEPARATOR() external view returns (bytes32 domainSeparator);\n\n    /**\n     * @notice get the current ERC2612 nonce for the given address\n     * @return current nonce\n     */\n    function nonces(address owner) external view returns (uint256);\n\n    /**\n     * @notice approve spender to transfer tokens held by owner via signature\n     * @dev this function may be vulnerable to approval replay attacks\n     * @param owner holder of tokens and signer of permit\n     * @param spender beneficiary of approval\n     * @param amount quantity of tokens to approve\n     * @param v secp256k1 'v' value\n     * @param r secp256k1 'r' value\n     * @param s secp256k1 's' value\n     */\n    function permit(\n        address owner,\n        address spender,\n        uint256 amount,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external;\n}\n"
      },
      "@solidstate/contracts/token/ERC20/permit/IERC2612Internal.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\ninterface IERC2612Internal {}\n"
      },
      "@solidstate/contracts/token/ERC721/base/ERC721Base.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { IERC721 } from '../../../interfaces/IERC721.sol';\nimport { IERC721Base } from './IERC721Base.sol';\nimport { ERC721BaseInternal } from './ERC721BaseInternal.sol';\n\n/**\n * @title Base ERC721 implementation, excluding optional extensions\n * @dev inheritor must either implement ERC165 supportsInterface or inherit ERC165Base\n */\nabstract contract ERC721Base is IERC721Base, ERC721BaseInternal {\n    /**\n     * @inheritdoc IERC721\n     */\n    function balanceOf(address account) external view returns (uint256) {\n        return _balanceOf(account);\n    }\n\n    /**\n     * @inheritdoc IERC721\n     */\n    function ownerOf(uint256 tokenId) external view returns (address) {\n        return _ownerOf(tokenId);\n    }\n\n    /**\n     * @inheritdoc IERC721\n     */\n    function getApproved(uint256 tokenId) external view returns (address) {\n        return _getApproved(tokenId);\n    }\n\n    /**\n     * @inheritdoc IERC721\n     */\n    function isApprovedForAll(\n        address account,\n        address operator\n    ) external view returns (bool) {\n        return _isApprovedForAll(account, operator);\n    }\n\n    /**\n     * @inheritdoc IERC721\n     */\n    function transferFrom(\n        address from,\n        address to,\n        uint256 tokenId\n    ) external payable {\n        _transferFrom(from, to, tokenId);\n    }\n\n    /**\n     * @inheritdoc IERC721\n     */\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 tokenId\n    ) external payable {\n        _safeTransferFrom(from, to, tokenId);\n    }\n\n    /**\n     * @inheritdoc IERC721\n     */\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 tokenId,\n        bytes memory data\n    ) external payable {\n        _safeTransferFrom(from, to, tokenId, data);\n    }\n\n    /**\n     * @inheritdoc IERC721\n     */\n    function approve(address operator, uint256 tokenId) external payable {\n        _approve(operator, tokenId);\n    }\n\n    /**\n     * @inheritdoc IERC721\n     */\n    function setApprovalForAll(address operator, bool status) external {\n        _setApprovalForAll(operator, status);\n    }\n}\n"
      },
      "@solidstate/contracts/token/ERC721/base/ERC721BaseInternal.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { IERC721Receiver } from '../../../interfaces/IERC721Receiver.sol';\nimport { EnumerableMap } from '../../../data/EnumerableMap.sol';\nimport { EnumerableSet } from '../../../data/EnumerableSet.sol';\nimport { AddressUtils } from '../../../utils/AddressUtils.sol';\nimport { IERC721BaseInternal } from './IERC721BaseInternal.sol';\nimport { ERC721BaseStorage } from './ERC721BaseStorage.sol';\n\n/**\n * @title Base ERC721 internal functions\n */\nabstract contract ERC721BaseInternal is IERC721BaseInternal {\n    using AddressUtils for address;\n    using EnumerableMap for EnumerableMap.UintToAddressMap;\n    using EnumerableSet for EnumerableSet.UintSet;\n\n    function _balanceOf(\n        address account\n    ) internal view virtual returns (uint256) {\n        if (account == address(0)) revert ERC721Base__BalanceQueryZeroAddress();\n        return ERC721BaseStorage.layout().holderTokens[account].length();\n    }\n\n    function _ownerOf(uint256 tokenId) internal view virtual returns (address) {\n        address owner = ERC721BaseStorage.layout().tokenOwners.get(tokenId);\n        if (owner == address(0)) revert ERC721Base__InvalidOwner();\n        return owner;\n    }\n\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\n        return ERC721BaseStorage.layout().tokenOwners.contains(tokenId);\n    }\n\n    function _getApproved(\n        uint256 tokenId\n    ) internal view virtual returns (address) {\n        if (!_exists(tokenId)) revert ERC721Base__NonExistentToken();\n\n        return ERC721BaseStorage.layout().tokenApprovals[tokenId];\n    }\n\n    function _isApprovedForAll(\n        address account,\n        address operator\n    ) internal view virtual returns (bool) {\n        return ERC721BaseStorage.layout().operatorApprovals[account][operator];\n    }\n\n    function _isApprovedOrOwner(\n        address spender,\n        uint256 tokenId\n    ) internal view virtual returns (bool) {\n        if (!_exists(tokenId)) revert ERC721Base__NonExistentToken();\n\n        address owner = _ownerOf(tokenId);\n\n        return (spender == owner ||\n            _getApproved(tokenId) == spender ||\n            _isApprovedForAll(owner, spender));\n    }\n\n    function _mint(address to, uint256 tokenId) internal virtual {\n        if (to == address(0)) revert ERC721Base__MintToZeroAddress();\n        if (_exists(tokenId)) revert ERC721Base__TokenAlreadyMinted();\n\n        _beforeTokenTransfer(address(0), to, tokenId);\n\n        ERC721BaseStorage.Layout storage l = ERC721BaseStorage.layout();\n\n        l.holderTokens[to].add(tokenId);\n        l.tokenOwners.set(tokenId, to);\n\n        emit Transfer(address(0), to, tokenId);\n    }\n\n    function _safeMint(address to, uint256 tokenId) internal virtual {\n        _safeMint(to, tokenId, '');\n    }\n\n    function _safeMint(\n        address to,\n        uint256 tokenId,\n        bytes memory data\n    ) internal virtual {\n        _mint(to, tokenId);\n        if (!_checkOnERC721Received(address(0), to, tokenId, data))\n            revert ERC721Base__ERC721ReceiverNotImplemented();\n    }\n\n    function _burn(uint256 tokenId) internal virtual {\n        address owner = _ownerOf(tokenId);\n\n        _beforeTokenTransfer(owner, address(0), tokenId);\n\n        ERC721BaseStorage.Layout storage l = ERC721BaseStorage.layout();\n\n        l.holderTokens[owner].remove(tokenId);\n        l.tokenOwners.remove(tokenId);\n\n        l.tokenApprovals[tokenId] = address(0);\n\n        emit Approval(owner, address(0), tokenId);\n        emit Transfer(owner, address(0), tokenId);\n    }\n\n    function _transfer(\n        address from,\n        address to,\n        uint256 tokenId\n    ) internal virtual {\n        address owner = _ownerOf(tokenId);\n\n        if (owner != from) revert ERC721Base__NotTokenOwner();\n        if (to == address(0)) revert ERC721Base__TransferToZeroAddress();\n\n        _beforeTokenTransfer(from, to, tokenId);\n\n        ERC721BaseStorage.Layout storage l = ERC721BaseStorage.layout();\n\n        l.holderTokens[from].remove(tokenId);\n        l.holderTokens[to].add(tokenId);\n        l.tokenOwners.set(tokenId, to);\n        l.tokenApprovals[tokenId] = address(0);\n\n        emit Approval(owner, address(0), tokenId);\n        emit Transfer(from, to, tokenId);\n    }\n\n    function _transferFrom(\n        address from,\n        address to,\n        uint256 tokenId\n    ) internal virtual {\n        _handleTransferMessageValue(from, to, tokenId, msg.value);\n        if (!_isApprovedOrOwner(msg.sender, tokenId))\n            revert ERC721Base__NotOwnerOrApproved();\n        _transfer(from, to, tokenId);\n    }\n\n    function _safeTransfer(\n        address from,\n        address to,\n        uint256 tokenId,\n        bytes memory data\n    ) internal virtual {\n        _transfer(from, to, tokenId);\n        if (!_checkOnERC721Received(from, to, tokenId, data))\n            revert ERC721Base__ERC721ReceiverNotImplemented();\n    }\n\n    function _safeTransferFrom(\n        address from,\n        address to,\n        uint256 tokenId\n    ) internal virtual {\n        _safeTransferFrom(from, to, tokenId, '');\n    }\n\n    function _safeTransferFrom(\n        address from,\n        address to,\n        uint256 tokenId,\n        bytes memory data\n    ) internal virtual {\n        _handleTransferMessageValue(from, to, tokenId, msg.value);\n        if (!_isApprovedOrOwner(msg.sender, tokenId))\n            revert ERC721Base__NotOwnerOrApproved();\n        _safeTransfer(from, to, tokenId, data);\n    }\n\n    function _approve(address operator, uint256 tokenId) internal virtual {\n        _handleApproveMessageValue(operator, tokenId, msg.value);\n\n        address owner = _ownerOf(tokenId);\n\n        if (operator == owner) revert ERC721Base__SelfApproval();\n        if (msg.sender != owner && !_isApprovedForAll(owner, msg.sender))\n            revert ERC721Base__NotOwnerOrApproved();\n\n        ERC721BaseStorage.layout().tokenApprovals[tokenId] = operator;\n        emit Approval(owner, operator, tokenId);\n    }\n\n    function _setApprovalForAll(\n        address operator,\n        bool status\n    ) internal virtual {\n        if (operator == msg.sender) revert ERC721Base__SelfApproval();\n        ERC721BaseStorage.layout().operatorApprovals[msg.sender][\n            operator\n        ] = status;\n        emit ApprovalForAll(msg.sender, operator, status);\n    }\n\n    function _checkOnERC721Received(\n        address from,\n        address to,\n        uint256 tokenId,\n        bytes memory data\n    ) internal virtual returns (bool) {\n        if (!to.isContract()) {\n            return true;\n        }\n\n        bytes memory returnData = to.functionCall(\n            abi.encodeWithSelector(\n                IERC721Receiver(to).onERC721Received.selector,\n                msg.sender,\n                from,\n                tokenId,\n                data\n            ),\n            'ERC721: transfer to non ERC721Receiver implementer'\n        );\n\n        bytes4 returnValue = abi.decode(returnData, (bytes4));\n        return returnValue == type(IERC721Receiver).interfaceId;\n    }\n\n    /**\n     * @notice ERC721 hook, called before externally called approvals for processing of included message value\n     * @param operator beneficiary of approval\n     * @param tokenId id of transferred token\n     * @param value message value\n     */\n    function _handleApproveMessageValue(\n        address operator,\n        uint256 tokenId,\n        uint256 value\n    ) internal virtual {}\n\n    /**\n     * @notice ERC721 hook, called before externally called transfers for processing of included message value\n     * @param from sender of token\n     * @param to receiver of token\n     * @param tokenId id of transferred token\n     * @param value message value\n     */\n    function _handleTransferMessageValue(\n        address from,\n        address to,\n        uint256 tokenId,\n        uint256 value\n    ) internal virtual {}\n\n    /**\n     * @notice ERC721 hook, called before all transfers including mint and burn\n     * @dev function should be overridden and new implementation must call super\n     * @param from sender of token\n     * @param to receiver of token\n     * @param tokenId id of transferred token\n     */\n    function _beforeTokenTransfer(\n        address from,\n        address to,\n        uint256 tokenId\n    ) internal virtual {}\n}\n"
      },
      "@solidstate/contracts/token/ERC721/base/ERC721BaseStorage.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { EnumerableMap } from '../../../data/EnumerableMap.sol';\nimport { EnumerableSet } from '../../../data/EnumerableSet.sol';\n\nlibrary ERC721BaseStorage {\n    using EnumerableSet for EnumerableSet.UintSet;\n    using EnumerableMap for EnumerableMap.UintToAddressMap;\n\n    bytes32 internal constant STORAGE_SLOT =\n        keccak256('solidstate.contracts.storage.ERC721Base');\n\n    struct Layout {\n        EnumerableMap.UintToAddressMap tokenOwners;\n        mapping(address => EnumerableSet.UintSet) holderTokens;\n        mapping(uint256 => address) tokenApprovals;\n        mapping(address => mapping(address => bool)) operatorApprovals;\n    }\n\n    function layout() internal pure returns (Layout storage l) {\n        bytes32 slot = STORAGE_SLOT;\n        assembly {\n            l.slot := slot\n        }\n    }\n}\n"
      },
      "@solidstate/contracts/token/ERC721/base/IERC721Base.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { IERC721 } from '../../../interfaces/IERC721.sol';\nimport { IERC721BaseInternal } from './IERC721BaseInternal.sol';\n\n/**\n * @title ERC721 base interface\n */\ninterface IERC721Base is IERC721BaseInternal, IERC721 {\n\n}\n"
      },
      "@solidstate/contracts/token/ERC721/base/IERC721BaseInternal.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { IERC721Internal } from '../../../interfaces/IERC721Internal.sol';\n\n/**\n * @title ERC721 base interface\n */\ninterface IERC721BaseInternal is IERC721Internal {\n    error ERC721Base__NotOwnerOrApproved();\n    error ERC721Base__SelfApproval();\n    error ERC721Base__BalanceQueryZeroAddress();\n    error ERC721Base__ERC721ReceiverNotImplemented();\n    error ERC721Base__InvalidOwner();\n    error ERC721Base__MintToZeroAddress();\n    error ERC721Base__NonExistentToken();\n    error ERC721Base__NotTokenOwner();\n    error ERC721Base__TokenAlreadyMinted();\n    error ERC721Base__TransferToZeroAddress();\n}\n"
      },
      "@solidstate/contracts/token/ERC721/enumerable/ERC721Enumerable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { EnumerableMap } from '../../../data/EnumerableMap.sol';\nimport { EnumerableSet } from '../../../data/EnumerableSet.sol';\nimport { ERC721BaseStorage } from '../base/ERC721BaseStorage.sol';\nimport { IERC721Enumerable } from './IERC721Enumerable.sol';\nimport { ERC721EnumerableInternal } from './ERC721EnumerableInternal.sol';\n\nabstract contract ERC721Enumerable is\n    IERC721Enumerable,\n    ERC721EnumerableInternal\n{\n    using EnumerableMap for EnumerableMap.UintToAddressMap;\n    using EnumerableSet for EnumerableSet.UintSet;\n\n    /**\n     * @inheritdoc IERC721Enumerable\n     */\n    function totalSupply() public view returns (uint256) {\n        return _totalSupply();\n    }\n\n    /**\n     * @inheritdoc IERC721Enumerable\n     */\n    function tokenOfOwnerByIndex(\n        address owner,\n        uint256 index\n    ) public view returns (uint256) {\n        return _tokenOfOwnerByIndex(owner, index);\n    }\n\n    /**\n     * @inheritdoc IERC721Enumerable\n     */\n    function tokenByIndex(uint256 index) public view returns (uint256) {\n        return _tokenByIndex(index);\n    }\n}\n"
      },
      "@solidstate/contracts/token/ERC721/enumerable/ERC721EnumerableInternal.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { EnumerableMap } from '../../../data/EnumerableMap.sol';\nimport { EnumerableSet } from '../../../data/EnumerableSet.sol';\nimport { ERC721BaseStorage } from '../base/ERC721BaseStorage.sol';\n\nabstract contract ERC721EnumerableInternal {\n    using EnumerableMap for EnumerableMap.UintToAddressMap;\n    using EnumerableSet for EnumerableSet.UintSet;\n\n    /**\n     * @notice TODO\n     */\n    function _totalSupply() internal view returns (uint256) {\n        return ERC721BaseStorage.layout().tokenOwners.length();\n    }\n\n    /**\n     * @notice TODO\n     */\n    function _tokenOfOwnerByIndex(\n        address owner,\n        uint256 index\n    ) internal view returns (uint256) {\n        return ERC721BaseStorage.layout().holderTokens[owner].at(index);\n    }\n\n    /**\n     * @notice TODO\n     */\n    function _tokenByIndex(\n        uint256 index\n    ) internal view returns (uint256 tokenId) {\n        (tokenId, ) = ERC721BaseStorage.layout().tokenOwners.at(index);\n    }\n}\n"
      },
      "@solidstate/contracts/token/ERC721/enumerable/IERC721Enumerable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\ninterface IERC721Enumerable {\n    /**\n     * @notice get total token supply\n     * @return total supply\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @notice get token of given owner at given internal storage index\n     * @param owner token holder to query\n     * @param index position in owner's token list to query\n     * @return tokenId id of retrieved token\n     */\n    function tokenOfOwnerByIndex(\n        address owner,\n        uint256 index\n    ) external view returns (uint256 tokenId);\n\n    /**\n     * @notice get token at given internal storage index\n     * @param index position in global token list to query\n     * @return tokenId id of retrieved token\n     */\n    function tokenByIndex(\n        uint256 index\n    ) external view returns (uint256 tokenId);\n}\n"
      },
      "@solidstate/contracts/token/ERC721/ISolidStateERC721.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { IERC721Base } from './base/IERC721Base.sol';\nimport { IERC721Enumerable } from './enumerable/IERC721Enumerable.sol';\nimport { IERC721Metadata } from './metadata/IERC721Metadata.sol';\n\ninterface ISolidStateERC721 is IERC721Base, IERC721Enumerable, IERC721Metadata {\n    error SolidStateERC721__PayableApproveNotSupported();\n    error SolidStateERC721__PayableTransferNotSupported();\n}\n"
      },
      "@solidstate/contracts/token/ERC721/metadata/ERC721Metadata.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { ERC721MetadataInternal } from './ERC721MetadataInternal.sol';\nimport { IERC721Metadata } from './IERC721Metadata.sol';\n\n/**\n * @title ERC721 metadata extensions\n */\nabstract contract ERC721Metadata is IERC721Metadata, ERC721MetadataInternal {\n    /**\n     * @notice inheritdoc IERC721Metadata\n     */\n    function name() external view virtual returns (string memory) {\n        return _name();\n    }\n\n    /**\n     * @notice inheritdoc IERC721Metadata\n     */\n    function symbol() external view virtual returns (string memory) {\n        return _symbol();\n    }\n\n    /**\n     * @notice inheritdoc IERC721Metadata\n     */\n    function tokenURI(\n        uint256 tokenId\n    ) external view virtual returns (string memory) {\n        return _tokenURI(tokenId);\n    }\n\n    /**\n     * @inheritdoc ERC721MetadataInternal\n     */\n    function _beforeTokenTransfer(\n        address from,\n        address to,\n        uint256 tokenId\n    ) internal virtual override {\n        super._beforeTokenTransfer(from, to, tokenId);\n    }\n}\n"
      },
      "@solidstate/contracts/token/ERC721/metadata/ERC721MetadataInternal.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { UintUtils } from '../../../utils/UintUtils.sol';\nimport { ERC721BaseStorage } from '../base/ERC721BaseStorage.sol';\nimport { ERC721BaseInternal } from '../base/ERC721Base.sol';\nimport { IERC721MetadataInternal } from './IERC721MetadataInternal.sol';\nimport { ERC721MetadataStorage } from './ERC721MetadataStorage.sol';\n\n/**\n * @title ERC721Metadata internal functions\n */\nabstract contract ERC721MetadataInternal is\n    IERC721MetadataInternal,\n    ERC721BaseInternal\n{\n    using UintUtils for uint256;\n\n    /**\n     * @notice get token name\n     * @return token name\n     */\n    function _name() internal view virtual returns (string memory) {\n        return ERC721MetadataStorage.layout().name;\n    }\n\n    /**\n     * @notice get token symbol\n     * @return token symbol\n     */\n    function _symbol() internal view virtual returns (string memory) {\n        return ERC721MetadataStorage.layout().symbol;\n    }\n\n    /**\n     * @notice get generated URI for given token\n     * @return token URI\n     */\n    function _tokenURI(\n        uint256 tokenId\n    ) internal view virtual returns (string memory) {\n        if (!_exists(tokenId)) revert ERC721Metadata__NonExistentToken();\n\n        ERC721MetadataStorage.Layout storage l = ERC721MetadataStorage.layout();\n\n        string memory tokenIdURI = l.tokenURIs[tokenId];\n        string memory baseURI = l.baseURI;\n\n        if (bytes(baseURI).length == 0) {\n            return tokenIdURI;\n        } else if (bytes(tokenIdURI).length > 0) {\n            return string(abi.encodePacked(baseURI, tokenIdURI));\n        } else {\n            return string(abi.encodePacked(baseURI, tokenId.toString()));\n        }\n    }\n\n    /**\n     * @notice ERC721 hook: clear per-token URI data on burn\n     * @inheritdoc ERC721BaseInternal\n     */\n    function _beforeTokenTransfer(\n        address from,\n        address to,\n        uint256 tokenId\n    ) internal virtual override {\n        super._beforeTokenTransfer(from, to, tokenId);\n\n        if (to == address(0)) {\n            delete ERC721MetadataStorage.layout().tokenURIs[tokenId];\n        }\n    }\n}\n"
      },
      "@solidstate/contracts/token/ERC721/metadata/ERC721MetadataStorage.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nlibrary ERC721MetadataStorage {\n    bytes32 internal constant STORAGE_SLOT =\n        keccak256('solidstate.contracts.storage.ERC721Metadata');\n\n    struct Layout {\n        string name;\n        string symbol;\n        string baseURI;\n        mapping(uint256 => string) tokenURIs;\n    }\n\n    function layout() internal pure returns (Layout storage l) {\n        bytes32 slot = STORAGE_SLOT;\n        assembly {\n            l.slot := slot\n        }\n    }\n}\n"
      },
      "@solidstate/contracts/token/ERC721/metadata/IERC721Metadata.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { IERC721MetadataInternal } from './IERC721MetadataInternal.sol';\n\n/**\n * @title ERC721Metadata interface\n */\ninterface IERC721Metadata is IERC721MetadataInternal {\n    /**\n     * @notice get token name\n     * @return token name\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @notice get token symbol\n     * @return token symbol\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @notice get generated URI for given token\n     * @return token URI\n     */\n    function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n"
      },
      "@solidstate/contracts/token/ERC721/metadata/IERC721MetadataInternal.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { IERC721BaseInternal } from '../base/IERC721BaseInternal.sol';\n\n/**\n * @title ERC721Metadata internal interface\n */\ninterface IERC721MetadataInternal is IERC721BaseInternal {\n    error ERC721Metadata__NonExistentToken();\n}\n"
      },
      "@solidstate/contracts/token/ERC721/SolidStateERC721.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { ERC165Base } from '../../introspection/ERC165/base/ERC165Base.sol';\nimport { ERC721Base, ERC721BaseInternal } from './base/ERC721Base.sol';\nimport { ERC721Enumerable } from './enumerable/ERC721Enumerable.sol';\nimport { ERC721Metadata } from './metadata/ERC721Metadata.sol';\nimport { ISolidStateERC721 } from './ISolidStateERC721.sol';\n\n/**\n * @title SolidState ERC721 implementation, including recommended extensions\n */\nabstract contract SolidStateERC721 is\n    ISolidStateERC721,\n    ERC721Base,\n    ERC721Enumerable,\n    ERC721Metadata,\n    ERC165Base\n{\n    /**\n     * @notice ERC721 hook: revert if value is included in external approve function call\n     * @inheritdoc ERC721BaseInternal\n     */\n    function _handleApproveMessageValue(\n        address operator,\n        uint256 tokenId,\n        uint256 value\n    ) internal virtual override {\n        if (value > 0) revert SolidStateERC721__PayableApproveNotSupported();\n        super._handleApproveMessageValue(operator, tokenId, value);\n    }\n\n    /**\n     * @notice ERC721 hook: revert if value is included in external transfer function call\n     * @inheritdoc ERC721BaseInternal\n     */\n    function _handleTransferMessageValue(\n        address from,\n        address to,\n        uint256 tokenId,\n        uint256 value\n    ) internal virtual override {\n        if (value > 0) revert SolidStateERC721__PayableTransferNotSupported();\n        super._handleTransferMessageValue(from, to, tokenId, value);\n    }\n\n    /**\n     * @inheritdoc ERC721BaseInternal\n     */\n    function _beforeTokenTransfer(\n        address from,\n        address to,\n        uint256 tokenId\n    ) internal virtual override(ERC721BaseInternal, ERC721Metadata) {\n        super._beforeTokenTransfer(from, to, tokenId);\n    }\n}\n"
      },
      "@solidstate/contracts/utils/AddressUtils.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { UintUtils } from './UintUtils.sol';\n\nlibrary AddressUtils {\n    using UintUtils for uint256;\n\n    error AddressUtils__InsufficientBalance();\n    error AddressUtils__NotContract();\n    error AddressUtils__SendValueFailed();\n\n    function toString(address account) internal pure returns (string memory) {\n        return uint256(uint160(account)).toHexString(20);\n    }\n\n    function isContract(address account) internal view returns (bool) {\n        uint256 size;\n        assembly {\n            size := extcodesize(account)\n        }\n        return size > 0;\n    }\n\n    function sendValue(address payable account, uint256 amount) internal {\n        (bool success, ) = account.call{ value: amount }('');\n        if (!success) revert AddressUtils__SendValueFailed();\n    }\n\n    function functionCall(\n        address target,\n        bytes memory data\n    ) internal returns (bytes memory) {\n        return\n            functionCall(target, data, 'AddressUtils: failed low-level call');\n    }\n\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory error\n    ) internal returns (bytes memory) {\n        return _functionCallWithValue(target, data, 0, error);\n    }\n\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value\n    ) internal returns (bytes memory) {\n        return\n            functionCallWithValue(\n                target,\n                data,\n                value,\n                'AddressUtils: failed low-level call with value'\n            );\n    }\n\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory error\n    ) internal returns (bytes memory) {\n        if (value > address(this).balance)\n            revert AddressUtils__InsufficientBalance();\n        return _functionCallWithValue(target, data, value, error);\n    }\n\n    /**\n     * @notice execute arbitrary external call with limited gas usage and amount of copied return data\n     * @dev derived from https://github.com/nomad-xyz/ExcessivelySafeCall (MIT License)\n     * @param target recipient of call\n     * @param gasAmount gas allowance for call\n     * @param value native token value to include in call\n     * @param maxCopy maximum number of bytes to copy from return data\n     * @param data encoded call data\n     * @return success whether call is successful\n     * @return returnData copied return data\n     */\n    function excessivelySafeCall(\n        address target,\n        uint256 gasAmount,\n        uint256 value,\n        uint16 maxCopy,\n        bytes memory data\n    ) internal returns (bool success, bytes memory returnData) {\n        returnData = new bytes(maxCopy);\n\n        assembly {\n            // execute external call via assembly to avoid automatic copying of return data\n            success := call(\n                gasAmount,\n                target,\n                value,\n                add(data, 0x20),\n                mload(data),\n                0,\n                0\n            )\n\n            // determine whether to limit amount of data to copy\n            let toCopy := returndatasize()\n\n            if gt(toCopy, maxCopy) {\n                toCopy := maxCopy\n            }\n\n            // store the length of the copied bytes\n            mstore(returnData, toCopy)\n\n            // copy the bytes from returndata[0:toCopy]\n            returndatacopy(add(returnData, 0x20), 0, toCopy)\n        }\n    }\n\n    function _functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory error\n    ) private returns (bytes memory) {\n        if (!isContract(target)) revert AddressUtils__NotContract();\n\n        (bool success, bytes memory returnData) = target.call{ value: value }(\n            data\n        );\n\n        if (success) {\n            return returnData;\n        } else if (returnData.length > 0) {\n            assembly {\n                let returnData_size := mload(returnData)\n                revert(add(32, returnData), returnData_size)\n            }\n        } else {\n            revert(error);\n        }\n    }\n}\n"
      },
      "@solidstate/contracts/utils/SafeERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { IERC20 } from '../interfaces/IERC20.sol';\nimport { AddressUtils } from './AddressUtils.sol';\n\n/**\n * @title Safe ERC20 interaction library\n * @dev derived from https://github.com/OpenZeppelin/openzeppelin-contracts/ (MIT license)\n */\nlibrary SafeERC20 {\n    using AddressUtils for address;\n\n    error SafeERC20__ApproveFromNonZeroToNonZero();\n    error SafeERC20__DecreaseAllowanceBelowZero();\n    error SafeERC20__OperationFailed();\n\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\n        _callOptionalReturn(\n            token,\n            abi.encodeWithSelector(token.transfer.selector, to, value)\n        );\n    }\n\n    function safeTransferFrom(\n        IERC20 token,\n        address from,\n        address to,\n        uint256 value\n    ) internal {\n        _callOptionalReturn(\n            token,\n            abi.encodeWithSelector(token.transferFrom.selector, from, to, value)\n        );\n    }\n\n    /**\n     * @dev safeApprove (like approve) should only be called when setting an initial allowance or when resetting it to zero; otherwise prefer safeIncreaseAllowance and safeDecreaseAllowance\n     */\n    function safeApprove(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        if ((value != 0) && (token.allowance(address(this), spender) != 0))\n            revert SafeERC20__ApproveFromNonZeroToNonZero();\n\n        _callOptionalReturn(\n            token,\n            abi.encodeWithSelector(token.approve.selector, spender, value)\n        );\n    }\n\n    function safeIncreaseAllowance(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        uint256 newAllowance = token.allowance(address(this), spender) + value;\n        _callOptionalReturn(\n            token,\n            abi.encodeWithSelector(\n                token.approve.selector,\n                spender,\n                newAllowance\n            )\n        );\n    }\n\n    function safeDecreaseAllowance(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        unchecked {\n            uint256 oldAllowance = token.allowance(address(this), spender);\n            if (oldAllowance < value)\n                revert SafeERC20__DecreaseAllowanceBelowZero();\n            uint256 newAllowance = oldAllowance - value;\n            _callOptionalReturn(\n                token,\n                abi.encodeWithSelector(\n                    token.approve.selector,\n                    spender,\n                    newAllowance\n                )\n            );\n        }\n    }\n\n    /**\n     * @notice send transaction data and check validity of return value, if present\n     * @param token ERC20 token interface\n     * @param data transaction data\n     */\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\n        bytes memory returndata = address(token).functionCall(\n            data,\n            'SafeERC20: low-level call failed'\n        );\n\n        if (returndata.length > 0) {\n            if (!abi.decode(returndata, (bool)))\n                revert SafeERC20__OperationFailed();\n        }\n    }\n}\n"
      },
      "@solidstate/contracts/utils/UintUtils.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\n/**\n * @title utility functions for uint256 operations\n * @dev derived from https://github.com/OpenZeppelin/openzeppelin-contracts/ (MIT license)\n */\nlibrary UintUtils {\n    error UintUtils__InsufficientHexLength();\n\n    bytes16 private constant HEX_SYMBOLS = '0123456789abcdef';\n\n    function add(uint256 a, int256 b) internal pure returns (uint256) {\n        return b < 0 ? sub(a, -b) : a + uint256(b);\n    }\n\n    function sub(uint256 a, int256 b) internal pure returns (uint256) {\n        return b < 0 ? add(a, -b) : a - uint256(b);\n    }\n\n    function toString(uint256 value) internal pure returns (string memory) {\n        if (value == 0) {\n            return '0';\n        }\n\n        uint256 temp = value;\n        uint256 digits;\n\n        while (temp != 0) {\n            digits++;\n            temp /= 10;\n        }\n\n        bytes memory buffer = new bytes(digits);\n\n        while (value != 0) {\n            digits -= 1;\n            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n            value /= 10;\n        }\n\n        return string(buffer);\n    }\n\n    function toHexString(uint256 value) internal pure returns (string memory) {\n        if (value == 0) {\n            return '0x00';\n        }\n\n        uint256 length = 0;\n\n        for (uint256 temp = value; temp != 0; temp >>= 8) {\n            unchecked {\n                length++;\n            }\n        }\n\n        return toHexString(value, length);\n    }\n\n    function toHexString(\n        uint256 value,\n        uint256 length\n    ) internal pure returns (string memory) {\n        bytes memory buffer = new bytes(2 * length + 2);\n        buffer[0] = '0';\n        buffer[1] = 'x';\n\n        unchecked {\n            for (uint256 i = 2 * length + 1; i > 1; --i) {\n                buffer[i] = HEX_SYMBOLS[value & 0xf];\n                value >>= 4;\n            }\n        }\n\n        if (value != 0) revert UintUtils__InsufficientHexLength();\n\n        return string(buffer);\n    }\n}\n"
      },
      "@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\nimport {IUniswapV3PoolImmutables} from './pool/IUniswapV3PoolImmutables.sol';\nimport {IUniswapV3PoolState} from './pool/IUniswapV3PoolState.sol';\nimport {IUniswapV3PoolDerivedState} from './pool/IUniswapV3PoolDerivedState.sol';\nimport {IUniswapV3PoolActions} from './pool/IUniswapV3PoolActions.sol';\nimport {IUniswapV3PoolOwnerActions} from './pool/IUniswapV3PoolOwnerActions.sol';\nimport {IUniswapV3PoolErrors} from './pool/IUniswapV3PoolErrors.sol';\nimport {IUniswapV3PoolEvents} from './pool/IUniswapV3PoolEvents.sol';\n\n/// @title The interface for a Uniswap V3 Pool\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\n/// to the ERC20 specification\n/// @dev The pool interface is broken up into many smaller pieces\ninterface IUniswapV3Pool is\n    IUniswapV3PoolImmutables,\n    IUniswapV3PoolState,\n    IUniswapV3PoolDerivedState,\n    IUniswapV3PoolActions,\n    IUniswapV3PoolOwnerActions,\n    IUniswapV3PoolErrors,\n    IUniswapV3PoolEvents\n{\n\n}\n"
      },
      "@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Permissionless pool actions\n/// @notice Contains pool methods that can be called by anyone\ninterface IUniswapV3PoolActions {\n    /// @notice Sets the initial price for the pool\n    /// @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value\n    /// @param sqrtPriceX96 the initial sqrt price of the pool as a Q64.96\n    function initialize(uint160 sqrtPriceX96) external;\n\n    /// @notice Adds liquidity for the given recipient/tickLower/tickUpper position\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3MintCallback#uniswapV3MintCallback\n    /// in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends\n    /// on tickLower, tickUpper, the amount of liquidity, and the current price.\n    /// @param recipient The address for which the liquidity will be created\n    /// @param tickLower The lower tick of the position in which to add liquidity\n    /// @param tickUpper The upper tick of the position in which to add liquidity\n    /// @param amount The amount of liquidity to mint\n    /// @param data Any data that should be passed through to the callback\n    /// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback\n    /// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback\n    function mint(\n        address recipient,\n        int24 tickLower,\n        int24 tickUpper,\n        uint128 amount,\n        bytes calldata data\n    ) external returns (uint256 amount0, uint256 amount1);\n\n    /// @notice Collects tokens owed to a position\n    /// @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity.\n    /// Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or\n    /// amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the\n    /// actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity.\n    /// @param recipient The address which should receive the fees collected\n    /// @param tickLower The lower tick of the position for which to collect fees\n    /// @param tickUpper The upper tick of the position for which to collect fees\n    /// @param amount0Requested How much token0 should be withdrawn from the fees owed\n    /// @param amount1Requested How much token1 should be withdrawn from the fees owed\n    /// @return amount0 The amount of fees collected in token0\n    /// @return amount1 The amount of fees collected in token1\n    function collect(\n        address recipient,\n        int24 tickLower,\n        int24 tickUpper,\n        uint128 amount0Requested,\n        uint128 amount1Requested\n    ) external returns (uint128 amount0, uint128 amount1);\n\n    /// @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position\n    /// @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0\n    /// @dev Fees must be collected separately via a call to #collect\n    /// @param tickLower The lower tick of the position for which to burn liquidity\n    /// @param tickUpper The upper tick of the position for which to burn liquidity\n    /// @param amount How much liquidity to burn\n    /// @return amount0 The amount of token0 sent to the recipient\n    /// @return amount1 The amount of token1 sent to the recipient\n    function burn(\n        int24 tickLower,\n        int24 tickUpper,\n        uint128 amount\n    ) external returns (uint256 amount0, uint256 amount1);\n\n    /// @notice Swap token0 for token1, or token1 for token0\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3SwapCallback#uniswapV3SwapCallback\n    /// @param recipient The address to receive the output of the swap\n    /// @param zeroForOne The direction of the swap, true for token0 to token1, false for token1 to token0\n    /// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)\n    /// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this\n    /// value after the swap. If one for zero, the price cannot be greater than this value after the swap\n    /// @param data Any data to be passed through to the callback\n    /// @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive\n    /// @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive\n    function swap(\n        address recipient,\n        bool zeroForOne,\n        int256 amountSpecified,\n        uint160 sqrtPriceLimitX96,\n        bytes calldata data\n    ) external returns (int256 amount0, int256 amount1);\n\n    /// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3FlashCallback#uniswapV3FlashCallback\n    /// @dev Can be used to donate underlying tokens pro-rata to currently in-range liquidity providers by calling\n    /// with 0 amount{0,1} and sending the donation amount(s) from the callback\n    /// @param recipient The address which will receive the token0 and token1 amounts\n    /// @param amount0 The amount of token0 to send\n    /// @param amount1 The amount of token1 to send\n    /// @param data Any data to be passed through to the callback\n    function flash(\n        address recipient,\n        uint256 amount0,\n        uint256 amount1,\n        bytes calldata data\n    ) external;\n\n    /// @notice Increase the maximum number of price and liquidity observations that this pool will store\n    /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to\n    /// the input observationCardinalityNext.\n    /// @param observationCardinalityNext The desired minimum number of observations for the pool to store\n    function increaseObservationCardinalityNext(uint16 observationCardinalityNext) external;\n}\n"
      },
      "@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Pool state that is not stored\n/// @notice Contains view functions to provide information about the pool that is computed rather than stored on the\n/// blockchain. The functions here may have variable gas costs.\ninterface IUniswapV3PoolDerivedState {\n    /// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp\n    /// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing\n    /// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick,\n    /// you must call it with secondsAgos = [3600, 0].\n    /// @dev The time weighted average tick represents the geometric time weighted average price of the pool, in\n    /// log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio.\n    /// @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned\n    /// @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp\n    /// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block\n    /// timestamp\n    function observe(uint32[] calldata secondsAgos)\n        external\n        view\n        returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s);\n\n    /// @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range\n    /// @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed.\n    /// I.e., snapshots cannot be compared if a position is not held for the entire period between when the first\n    /// snapshot is taken and the second snapshot is taken.\n    /// @param tickLower The lower tick of the range\n    /// @param tickUpper The upper tick of the range\n    /// @return tickCumulativeInside The snapshot of the tick accumulator for the range\n    /// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range\n    /// @return secondsInside The snapshot of seconds per liquidity for the range\n    function snapshotCumulativesInside(int24 tickLower, int24 tickUpper)\n        external\n        view\n        returns (\n            int56 tickCumulativeInside,\n            uint160 secondsPerLiquidityInsideX128,\n            uint32 secondsInside\n        );\n}\n"
      },
      "@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolErrors.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Errors emitted by a pool\n/// @notice Contains all events emitted by the pool\ninterface IUniswapV3PoolErrors {\n    error LOK();\n    error TLU();\n    error TLM();\n    error TUM();\n    error AI();\n    error M0();\n    error M1();\n    error AS();\n    error IIA();\n    error L();\n    error F0();\n    error F1();\n}\n"
      },
      "@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Events emitted by a pool\n/// @notice Contains all events emitted by the pool\ninterface IUniswapV3PoolEvents {\n    /// @notice Emitted exactly once by a pool when #initialize is first called on the pool\n    /// @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize\n    /// @param sqrtPriceX96 The initial sqrt price of the pool, as a Q64.96\n    /// @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool\n    event Initialize(uint160 sqrtPriceX96, int24 tick);\n\n    /// @notice Emitted when liquidity is minted for a given position\n    /// @param sender The address that minted the liquidity\n    /// @param owner The owner of the position and recipient of any minted liquidity\n    /// @param tickLower The lower tick of the position\n    /// @param tickUpper The upper tick of the position\n    /// @param amount The amount of liquidity minted to the position range\n    /// @param amount0 How much token0 was required for the minted liquidity\n    /// @param amount1 How much token1 was required for the minted liquidity\n    event Mint(\n        address sender,\n        address indexed owner,\n        int24 indexed tickLower,\n        int24 indexed tickUpper,\n        uint128 amount,\n        uint256 amount0,\n        uint256 amount1\n    );\n\n    /// @notice Emitted when fees are collected by the owner of a position\n    /// @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees\n    /// @param owner The owner of the position for which fees are collected\n    /// @param tickLower The lower tick of the position\n    /// @param tickUpper The upper tick of the position\n    /// @param amount0 The amount of token0 fees collected\n    /// @param amount1 The amount of token1 fees collected\n    event Collect(\n        address indexed owner,\n        address recipient,\n        int24 indexed tickLower,\n        int24 indexed tickUpper,\n        uint128 amount0,\n        uint128 amount1\n    );\n\n    /// @notice Emitted when a position's liquidity is removed\n    /// @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect\n    /// @param owner The owner of the position for which liquidity is removed\n    /// @param tickLower The lower tick of the position\n    /// @param tickUpper The upper tick of the position\n    /// @param amount The amount of liquidity to remove\n    /// @param amount0 The amount of token0 withdrawn\n    /// @param amount1 The amount of token1 withdrawn\n    event Burn(\n        address indexed owner,\n        int24 indexed tickLower,\n        int24 indexed tickUpper,\n        uint128 amount,\n        uint256 amount0,\n        uint256 amount1\n    );\n\n    /// @notice Emitted by the pool for any swaps between token0 and token1\n    /// @param sender The address that initiated the swap call, and that received the callback\n    /// @param recipient The address that received the output of the swap\n    /// @param amount0 The delta of the token0 balance of the pool\n    /// @param amount1 The delta of the token1 balance of the pool\n    /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96\n    /// @param liquidity The liquidity of the pool after the swap\n    /// @param tick The log base 1.0001 of price of the pool after the swap\n    event Swap(\n        address indexed sender,\n        address indexed recipient,\n        int256 amount0,\n        int256 amount1,\n        uint160 sqrtPriceX96,\n        uint128 liquidity,\n        int24 tick\n    );\n\n    /// @notice Emitted by the pool for any flashes of token0/token1\n    /// @param sender The address that initiated the swap call, and that received the callback\n    /// @param recipient The address that received the tokens from flash\n    /// @param amount0 The amount of token0 that was flashed\n    /// @param amount1 The amount of token1 that was flashed\n    /// @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee\n    /// @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee\n    event Flash(\n        address indexed sender,\n        address indexed recipient,\n        uint256 amount0,\n        uint256 amount1,\n        uint256 paid0,\n        uint256 paid1\n    );\n\n    /// @notice Emitted by the pool for increases to the number of observations that can be stored\n    /// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index\n    /// just before a mint/swap/burn.\n    /// @param observationCardinalityNextOld The previous value of the next observation cardinality\n    /// @param observationCardinalityNextNew The updated value of the next observation cardinality\n    event IncreaseObservationCardinalityNext(\n        uint16 observationCardinalityNextOld,\n        uint16 observationCardinalityNextNew\n    );\n\n    /// @notice Emitted when the protocol fee is changed by the pool\n    /// @param feeProtocol0Old The previous value of the token0 protocol fee\n    /// @param feeProtocol1Old The previous value of the token1 protocol fee\n    /// @param feeProtocol0New The updated value of the token0 protocol fee\n    /// @param feeProtocol1New The updated value of the token1 protocol fee\n    event SetFeeProtocol(uint8 feeProtocol0Old, uint8 feeProtocol1Old, uint8 feeProtocol0New, uint8 feeProtocol1New);\n\n    /// @notice Emitted when the collected protocol fees are withdrawn by the factory owner\n    /// @param sender The address that collects the protocol fees\n    /// @param recipient The address that receives the collected protocol fees\n    /// @param amount0 The amount of token0 protocol fees that is withdrawn\n    /// @param amount0 The amount of token1 protocol fees that is withdrawn\n    event CollectProtocol(address indexed sender, address indexed recipient, uint128 amount0, uint128 amount1);\n}\n"
      },
      "@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Pool state that never changes\n/// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values\ninterface IUniswapV3PoolImmutables {\n    /// @notice The contract that deployed the pool, which must adhere to the IUniswapV3Factory interface\n    /// @return The contract address\n    function factory() external view returns (address);\n\n    /// @notice The first of the two tokens of the pool, sorted by address\n    /// @return The token contract address\n    function token0() external view returns (address);\n\n    /// @notice The second of the two tokens of the pool, sorted by address\n    /// @return The token contract address\n    function token1() external view returns (address);\n\n    /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6\n    /// @return The fee\n    function fee() external view returns (uint24);\n\n    /// @notice The pool tick spacing\n    /// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive\n    /// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ...\n    /// This value is an int24 to avoid casting even though it is always positive.\n    /// @return The tick spacing\n    function tickSpacing() external view returns (int24);\n\n    /// @notice The maximum amount of position liquidity that can use any tick in the range\n    /// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and\n    /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool\n    /// @return The max amount of liquidity per tick\n    function maxLiquidityPerTick() external view returns (uint128);\n}\n"
      },
      "@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Permissioned pool actions\n/// @notice Contains pool methods that may only be called by the factory owner\ninterface IUniswapV3PoolOwnerActions {\n    /// @notice Set the denominator of the protocol's % share of the fees\n    /// @param feeProtocol0 new protocol fee for token0 of the pool\n    /// @param feeProtocol1 new protocol fee for token1 of the pool\n    function setFeeProtocol(uint8 feeProtocol0, uint8 feeProtocol1) external;\n\n    /// @notice Collect the protocol fee accrued to the pool\n    /// @param recipient The address to which collected protocol fees should be sent\n    /// @param amount0Requested The maximum amount of token0 to send, can be 0 to collect fees in only token1\n    /// @param amount1Requested The maximum amount of token1 to send, can be 0 to collect fees in only token0\n    /// @return amount0 The protocol fee collected in token0\n    /// @return amount1 The protocol fee collected in token1\n    function collectProtocol(\n        address recipient,\n        uint128 amount0Requested,\n        uint128 amount1Requested\n    ) external returns (uint128 amount0, uint128 amount1);\n}\n"
      },
      "@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Pool state that can change\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\n/// per transaction\ninterface IUniswapV3PoolState {\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\n    /// when accessed externally.\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\n    /// @return tick The current tick of the pool, i.e. according to the last tick transition that was run.\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\n    /// boundary.\n    /// @return observationIndex The index of the last oracle observation that was written,\n    /// @return observationCardinality The current maximum number of observations stored in the pool,\n    /// @return observationCardinalityNext The next maximum number of observations, to be updated when the observation.\n    /// @return feeProtocol The protocol fee for both tokens of the pool.\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\n    /// unlocked Whether the pool is currently locked to reentrancy\n    function slot0()\n        external\n        view\n        returns (\n            uint160 sqrtPriceX96,\n            int24 tick,\n            uint16 observationIndex,\n            uint16 observationCardinality,\n            uint16 observationCardinalityNext,\n            uint8 feeProtocol,\n            bool unlocked\n        );\n\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\n    /// @dev This value can overflow the uint256\n    function feeGrowthGlobal0X128() external view returns (uint256);\n\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\n    /// @dev This value can overflow the uint256\n    function feeGrowthGlobal1X128() external view returns (uint256);\n\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\n    /// @dev Protocol fees will never exceed uint128 max in either token\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\n\n    /// @notice The currently in range liquidity available to the pool\n    /// @dev This value has no relationship to the total liquidity across all ticks\n    /// @return The liquidity at the current price of the pool\n    function liquidity() external view returns (uint128);\n\n    /// @notice Look up information about a specific tick in the pool\n    /// @param tick The tick to look up\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\n    /// tick upper\n    /// @return liquidityNet how much liquidity changes when the pool price crosses the tick,\n    /// @return feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\n    /// @return feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\n    /// @return tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\n    /// @return secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\n    /// @return secondsOutside the seconds spent on the other side of the tick from the current tick,\n    /// @return initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\n    /// a specific position.\n    function ticks(int24 tick)\n        external\n        view\n        returns (\n            uint128 liquidityGross,\n            int128 liquidityNet,\n            uint256 feeGrowthOutside0X128,\n            uint256 feeGrowthOutside1X128,\n            int56 tickCumulativeOutside,\n            uint160 secondsPerLiquidityOutsideX128,\n            uint32 secondsOutside,\n            bool initialized\n        );\n\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\n\n    /// @notice Returns the information about a position by the position's key\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\n    /// @return liquidity The amount of liquidity in the position,\n    /// @return feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\n    /// @return feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\n    /// @return tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\n    /// @return tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\n    function positions(bytes32 key)\n        external\n        view\n        returns (\n            uint128 liquidity,\n            uint256 feeGrowthInside0LastX128,\n            uint256 feeGrowthInside1LastX128,\n            uint128 tokensOwed0,\n            uint128 tokensOwed1\n        );\n\n    /// @notice Returns data about a specific observation index\n    /// @param index The element of the observations array to fetch\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\n    /// ago, rather than at a specific index in the array.\n    /// @return blockTimestamp The timestamp of the observation,\n    /// @return tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\n    /// @return secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\n    /// @return initialized whether the observation has been initialized and the values are safe to use\n    function observations(uint256 index)\n        external\n        view\n        returns (\n            uint32 blockTimestamp,\n            int56 tickCumulative,\n            uint160 secondsPerLiquidityCumulativeX128,\n            bool initialized\n        );\n}\n"
      },
      "contracts/Accountant.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nimport { IERC20 } from '@solidstate/contracts/interfaces/IERC20.sol';\nimport { SafeERC20 } from '@solidstate/contracts/utils/SafeERC20.sol';\nimport { AddressUtils } from '@solidstate/contracts/utils/AddressUtils.sol';\n\nimport { Registry } from './registry/Registry.sol';\nimport { RegistryStorage } from './registry/RegistryStorage.sol';\nimport { VaultBaseExternal } from './vault-base/VaultBaseExternal.sol';\nimport { IAggregatorV3Interface } from './interfaces/IAggregatorV3Interface.sol';\nimport { IValioCustomAggregator } from './aggregators/IValioCustomAggregator.sol';\nimport { IValuer } from './valuers/IValuer.sol';\n\nimport { Constants } from './lib/Constants.sol';\n\n/**\n * @title   Accountant\n * @notice  Logic for aggregating the value of assets in a vault\n * @dev     It uses the valuers to get the value of the assets in the vault in USD\n * @dev     Has some external helper functions to check if an asset is supported, deprecated, hard deprecated, etc\n * @dev     For erc20 assets, minValue and maxValue are the same.\n * @dev     For other assets like perps, maxValue is the gross value, minValue is gross - fees (net value)\n */\n\ncontract Accountant {\n    using AddressUtils for address;\n\n    // The valio registry\n    Registry public immutable registry;\n\n    constructor(address _registry) {\n        require(_registry != address(0), 'Invalid registry');\n        registry = Registry(_registry);\n    }\n\n    /**\n     * @notice  Get the value of a vault in USD\n     * @param   vault  The vault address\n     * @return  minValue  The min value of the vault in USD (net)\n     * @return  maxValue  The max value of the vault in USD (gross)\n     * @return  hasHardDeprecatedAsset  True if the vault has a hard deprecated asset\n     */\n    function getVaultValue(\n        address vault\n    )\n        external\n        view\n        returns (uint minValue, uint maxValue, bool hasHardDeprecatedAsset)\n    {\n        address[] memory activeAssets = VaultBaseExternal(payable(vault))\n            .assetsWithBalances();\n        for (uint i = 0; i < activeAssets.length; i++) {\n            if (_isHardDeprecated(activeAssets[i])) {\n                hasHardDeprecatedAsset = true;\n            }\n            (uint minAssetValue, uint maxAssetValue) = _assetValueOfVault(\n                activeAssets[i],\n                vault\n            );\n            minValue += minAssetValue;\n            maxValue += maxAssetValue;\n        }\n    }\n\n    /**\n     * @notice  Returns the value of an asset in a vault\n     * @param   asset  The asset\n     * @param   vault  The valio vault\n     * @return  minValue  The net value of the asset in the vault in USD\n     * @return  maxValue  The gross value of the asset in the vault in USD\n     */\n    function assetValueOfVault(\n        address asset,\n        address vault\n    ) external view returns (uint minValue, uint maxValue) {\n        return _assetValueOfVault(asset, vault);\n    }\n\n    /**\n     * @notice  Returns the value of a given amount of an asseet\n     * @dev     Only usable for erc20/fungible assets\n     * @param   asset  The asset\n     * @param   amount  The amount of the asset\n     * @return  minValue  The min value of the asset in USD\n     * @return  maxValue  The max value of the asset in USD\n     */\n    function assetValue(\n        address asset,\n        uint amount\n    ) external view returns (uint minValue, uint maxValue) {\n        int256 unitPrice = _getUSDPrice(asset);\n        address valuer = registry.valuers(asset);\n        require(valuer != address(0), 'No valuer');\n        return IValuer(valuer).getAssetValue(amount, asset, unitPrice);\n    }\n\n    /**\n     * @notice  Returns the balance and value of each asset in a vault\n     * @dev     The balance is 0 for non fungible assets\n     * @param   vault  The valio vault\n     * @return  IValuer.AssetValue[]  The breakdown of the assets + value in the vault\n     */\n    function assetBreakDownOfVault(\n        address vault\n    ) external view returns (IValuer.AssetValue[] memory) {\n        address[] memory activeAssets = VaultBaseExternal(payable(vault))\n            .assetsWithBalances();\n        IValuer.AssetValue[] memory ava = new IValuer.AssetValue[](\n            activeAssets.length\n        );\n        for (uint i = 0; i < activeAssets.length; i++) {\n            // Hard deprecated assets have 0 value, but they can be traded out of\n            bool hardDeprecated = registry.hardDeprecatedAssets(\n                activeAssets[i]\n            );\n\n            int256 unitPrice = hardDeprecated\n                ? int256(0)\n                : _getUSDPrice(activeAssets[i]);\n            address valuer = registry.valuers(activeAssets[i]);\n            require(valuer != address(0), 'No valuer');\n            ava[i] = IValuer(valuer).getAssetBreakdown(\n                vault,\n                activeAssets[i],\n                unitPrice\n            );\n        }\n        return ava;\n    }\n\n    /**\n     * @notice  Returns if an asset is active in a vault\n     * @param   asset  The asset\n     * @param   vault  The valio vault\n     * @return  bool  True if the asset is active in the vault (tracked)\n     */\n    function assetIsActive(\n        address asset,\n        address vault\n    ) external view returns (bool) {\n        return _assetIsActive(asset, vault);\n    }\n\n    /**\n     * @notice  Returns if valio supports the asset\n     * @dev     An asset is supported if it has a valuer\n     * @dev     The asset could still be hard deprecated\n     * @param   asset  The asset\n     * @return  bool  True if the asset is supported\n     */\n    function isSupportedAsset(address asset) external view returns (bool) {\n        return registry.valuers(asset) != address(0);\n    }\n\n    /**\n     * @notice  Returns if an asset is deprecated\n     * @dev     An asset is deprecated if we are going to stop supporting it\n     * @dev     A deprecated asset can be traded out of, but not into\n     * @param   asset  The asset\n     * @return  bool  True if the asset is deprecated\n     */\n    function isDeprecated(address asset) external view returns (bool) {\n        return registry.deprecatedAssets(asset);\n    }\n\n    /**\n     * @notice  Returns if an asset is hard deprecated\n     * @dev     A hard asset can no longer be valued, and has 0 value\n     * @dev     Vaults with a hard deprecated asset cannot be deposited\n     * @param   asset  The asset\n     * @return  bool  True if the asset is hard deprecated\n     */\n    function isHardDeprecated(address asset) external view returns (bool) {\n        return _isHardDeprecated(asset);\n    }\n\n    /**\n     * @notice  Returns the value of an asset in a vault\n     * @param   asset  The asset\n     * @param   vault  The valio vault\n     * @return  minValue  The net value of the asset in the vault in USD\n     * @return  maxValue  The gross value of the asset in the vault in USD\n     */\n    function _assetValueOfVault(\n        address asset,\n        address vault\n    ) internal view returns (uint minValue, uint maxValue) {\n        // Hard deprecated assets have 0 value, but they can be traded out of\n        if (registry.hardDeprecatedAssets(asset)) {\n            return (0, 0);\n        }\n        int256 unitPrice = _getUSDPrice(asset);\n        address valuer = registry.valuers(asset);\n        require(valuer != address(0), 'No valuer');\n        return IValuer(valuer).getVaultValue(vault, asset, unitPrice);\n    }\n\n    /**\n     * @notice  Returns if an asset is active in a vault\n     * @param   asset  The asset\n     * @param   vault  The valio vault\n     * @return  bool  True if the asset is active in the vault (tracked)\n     */\n    function _assetIsActive(\n        address asset,\n        address vault\n    ) internal view returns (bool) {\n        address valuer = registry.valuers(asset);\n        require(valuer != address(0), 'No valuer');\n        return IValuer(valuer).getAssetActive(vault, asset);\n    }\n\n    /**\n     * @notice  Returns if an asset is hard deprecated\n     * @dev     A hard asset can no longer be valued, and has 0 value\n     * @dev     Vaults with a hard deprecated asset cannot be deposited\n     * @param   asset  The asset\n     * @return  bool  True if the asset is hard deprecated\n     */\n    function _isHardDeprecated(address asset) internal view returns (bool) {\n        return registry.hardDeprecatedAssets(asset);\n    }\n\n    /**\n     * @notice  Returns the price of a single unit of the given asset in USD\n     * @dev     The price is @ VAULT_PRECISION\n     * @param   asset  The asset\n     * @return  price  The price of a single unit of the asset in USD\n     */\n    function _getUSDPrice(address asset) internal view returns (int256 price) {\n        uint256 updatedAt;\n\n        RegistryStorage.AggregatorType aggregatorType = registry\n            .assetAggregatorType(asset);\n        if (aggregatorType == RegistryStorage.AggregatorType.None) {\n            return 0;\n        } else if (\n            aggregatorType == RegistryStorage.AggregatorType.ChainlinkV3USD\n        ) {\n            IAggregatorV3Interface chainlinkAggregator = registry\n                .chainlinkV3USDAggregators(asset);\n            require(\n                address(chainlinkAggregator) != address(0),\n                'No cl aggregator'\n            );\n            (, price, , updatedAt, ) = chainlinkAggregator.latestRoundData();\n        } else {\n            IValioCustomAggregator valioAggregator = registry\n                .valioCustomUSDAggregators(aggregatorType);\n\n            require(address(valioAggregator) != address(0), 'No vl aggregator');\n            (price, updatedAt) = valioAggregator.latestRoundData(asset);\n        }\n\n        require(\n            updatedAt + registry.chainlinkTimeout() >= block.timestamp,\n            'Price expired'\n        );\n\n        require(price > 0, 'Price not available');\n\n        price = (price * int(Constants.VAULT_PRECISION)) / 10 ** 8;\n    }\n}\n"
      },
      "contracts/aggregators/IValioCustomAggregator.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\n/**\n * @title   IValioCustomAggregator\n * @notice  Interface for custom price aggregators\n * @dev     It takes the asset we are trying to value and returns the price of that asset\n * @dev     A custom aggregator can be shared between multiple assets, unline a chainlink aggregator\n */\n\ninterface IValioCustomAggregator {\n    function description() external view returns (string memory);\n\n    function decimals() external view returns (uint8);\n\n    function latestRoundData(\n        address asset\n    ) external view returns (int256 answer, uint256 updatedAt);\n}\n"
      },
      "contracts/cpit/CPIT.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\nimport { CPITStorage } from './CPITStorage.sol';\nimport { Constants } from '../lib/Constants.sol';\n\n/**\n * @title   CPIT (Cumulative Price Impact Threshold) contract\n * @notice  The CPIT contract is used to calculate, store and check the cumulative price impact of trades.\n * @notice  The impact is calculated against the total AUM of a vault.\n * @notice  The priceImpact is the change in the value of the AUM\n * @dev     The allowed max24HourCPITBips is based on the RiskProfile of the vault\n * @dev     We store the priceImpact for each 6 hour window and\n * @dev     calculate the cumulative price impact for the last 24 hours\n */\ncontract CPIT {\n    uint256 private constant WINDOW_SIZE = 6 hours; // window size for rolling 24 hours\n\n    /**\n     * @notice  Update the cumulative price impact threshold (CPIT) for a trade\n     * @dev     Will revert if the 24 hour cumulative price impact threshold is exceeded\n     * @dev     This will rollback the trade tx\n     * @param   preTransactionValue  The AUM of the vault pre trade\n     * @param   postTransactionValue  The AUM of the vault post trade\n     * @param   max24HourCPITBips  The max 24 hour cumulative price impact threshold in BIPs\n     * @return  priceImpactBips  The price impact of the trade in BIPs (not currently used)\n     */\n    function _updatePriceImpact(\n        uint preTransactionValue,\n        uint postTransactionValue,\n        uint max24HourCPITBips\n    ) internal returns (uint priceImpactBips) {\n        CPITStorage.Layout storage l = CPITStorage.layout();\n        // calculate price impact in BIPs\n        priceImpactBips = _calculatePriceImpact(\n            preTransactionValue,\n            postTransactionValue\n        );\n\n        if (priceImpactBips == 0) {\n            return priceImpactBips;\n        }\n\n        uint currentWindow = _getCurrentWindow();\n\n        // update priceImpact for current window\n        l.deviation[currentWindow] += priceImpactBips;\n\n        uint cumulativePriceImpact = _calculateCumulativePriceImpact(\n            currentWindow\n        );\n\n        // check if 24 hour cumulative price impact threshold is exceeded\n        if (cumulativePriceImpact > max24HourCPITBips) {\n            revert('CPIT: price impact exceeded');\n        }\n    }\n\n    /**\n     * @notice  Returns the accumulated price impact for the last 24 hours\n     * @dev     The price impact is fetched for each 6 hour window and summed to get the cumulative price impact\n     * @return  uint256  .\n     */\n    function _getCurrentCpit() internal view returns (uint256) {\n        return _calculateCumulativePriceImpact(_getCurrentWindow());\n    }\n\n    /**\n     * @notice  Returns the current 24 hour window\n     * @return  currentWindow  The current 24 hour window\n     */\n    function _getCurrentWindow() internal view returns (uint256 currentWindow) {\n        currentWindow = block.timestamp / WINDOW_SIZE;\n    }\n\n    // calculate the 24 hour cumulative price impact\n    /**\n     * @notice  Calculate the cumulative price impact for the last 24 hours\n     * @dev     The price impact is fetched for each 6 hour window and summed to get the cumulative price impact\n     * @param   currentWindow  The current 24 hour window\n     * @return  cumulativePriceImpact  The cumulative price impact for the last 24 hours\n     */\n    function _calculateCumulativePriceImpact(\n        uint currentWindow\n    ) internal view returns (uint cumulativePriceImpact) {\n        CPITStorage.Layout storage l = CPITStorage.layout();\n        uint windowsInDay = 24 hours / WINDOW_SIZE;\n        uint startWindow = currentWindow - (windowsInDay - 1);\n        for (uint256 i = startWindow; i <= currentWindow; i++) {\n            cumulativePriceImpact += l.deviation[i];\n        }\n    }\n\n    /**\n     * @notice  Calculate the price impact of a trade in BIPS\n     * @param   oldValue  The previous AUM\n     * @param   newValue  The new AUM\n     * @return  priceImpactBips  The price impact of the trade in BIPs\n     */\n    function _calculatePriceImpact(\n        uint oldValue,\n        uint newValue\n    ) internal pure returns (uint priceImpactBips) {\n        if (newValue >= oldValue) {\n            return 0;\n        }\n        // Calculate the deviation between the old and new values\n        uint deviation = oldValue - newValue;\n        // Calculate the impact on price in basis points (BIPs)\n        priceImpactBips = ((deviation * Constants.BASIS_POINTS_DIVISOR) /\n            oldValue);\n    }\n}\n"
      },
      "contracts/cpit/CPITStorage.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nlibrary CPITStorage {\n    bytes32 internal constant STORAGE_SLOT = keccak256('valio.storage.CPIT');\n\n    // solhint-disable-next-line ordering\n    struct Layout {\n        uint256 DEPRECATED_lockedUntil; // timestamp of when vault is locked until\n        mapping(uint256 => uint) deviation; // deviation for each window\n    }\n\n    function layout() internal pure returns (Layout storage l) {\n        bytes32 slot = STORAGE_SLOT;\n\n        assembly {\n            l.slot := slot\n        }\n    }\n}\n"
      },
      "contracts/executors/IExecutor.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nimport { IExecutorEvents, ExecutorIntegration } from './IExecutorEvents.sol';\n\ninterface IExecutor is IExecutorEvents {\n    error NotImplemented();\n\n    /**\n     * @notice  Some integrations may need some logic executed to tidy up valio storage\n     *          if/when a an action happens on an external protocol\n     * @dev     For instance GMX positions are Liquidated with out a callback, we need\n     *          to clear these positions from valio storage\n     */\n    function clean() external;\n\n    function requiresCPIT() external returns (bool);\n}\n"
      },
      "contracts/executors/IExecutorEvents.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nenum ExecutorIntegration {\n    ZeroX,\n    GMX,\n    SnxPerpsV2,\n    GMXOrderBook\n}\n\n// These are all in the one interface to make it easier to track all the events\ninterface IExecutorEvents {\n    // 0x\n    event ZeroXSwap(\n        address indexed sellTokenAddress,\n        uint sellAmount,\n        address indexed buyTokenAddress,\n        uint buyAmount,\n        uint amountReceived,\n        uint unitPrice\n    );\n\n    // Gmx V1\n    event GmxV1CreateIncreasePosition(\n        bool isLong,\n        address indexToken,\n        address collateralToken,\n        uint sizeDelta,\n        uint collateralAmount,\n        uint acceptablePrice\n    );\n\n    event GmxV1CreateDecreasePosition(\n        bool isLong,\n        address indexToken,\n        address collateralToken,\n        uint sizeDelta,\n        uint collateralDelta,\n        uint acceptablePrice\n    );\n\n    event GmxV1Callback(\n        bool isIncrease,\n        bool isLong,\n        address indexToken,\n        address collateralToken,\n        bool wasExecuted,\n        uint executionPrice\n    );\n\n    event GmxV1CreateDecreaseOrder(\n        address _indexToken,\n        uint256 _sizeDelta,\n        address _collateralToken,\n        uint256 _collateralDelta,\n        bool _isLong,\n        uint256 _triggerPrice,\n        bool _triggerAboveThreshold\n    );\n\n    event GmxV1UpdateDecreaseOrder(\n        uint256 _orderIndex,\n        address _indexToken,\n        uint256 _sizeDelta,\n        address _collateralToken,\n        uint256 _collateralDelta,\n        bool _isLong,\n        uint256 _triggerPrice,\n        bool _triggerAboveThreshold\n    );\n\n    event GmxV1CancelDecreaseOrder(\n        uint256 _orderIndex,\n        address _indexToken,\n        address _collateralToken,\n        bool _isLong\n    );\n\n    // Perps V2\n    event PerpsV2ExecutedManagerActionDeposit(\n        address wrapper,\n        address perpMarket,\n        address inputToken,\n        uint inputTokenAmount\n    );\n\n    event PerpsV2ExecutedManagerActionWithdraw(\n        address wrapper,\n        address perpMarket,\n        address outputToken,\n        uint outputTokenAmount\n    );\n\n    event PerpsV2ExecutedManagerActionSubmitOrder(\n        address wrapper,\n        address perpMarket,\n        int sizeDelta,\n        uint desiredFillPrice\n    );\n\n    event PerpsV2ExecutedManagerActionSubmitCloseOrder(\n        address wrapper,\n        address perpMarket,\n        uint desiredFillPrice\n    );\n\n    event PerpsV2ExecutedManagerActionSubmitCancelOrder(\n        address wrapper,\n        address perpMarket\n    );\n}\n"
      },
      "contracts/GmxConfig.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\nimport { IGmxRouter } from './interfaces/IGmxRouter.sol';\nimport { IGmxVault } from './interfaces/IGmxVault.sol';\nimport { IGmxOrderBook } from './interfaces/IGmxOrderBook.sol';\nimport { IGmxPositionRouter } from './interfaces/IGmxPositionRouter.sol';\n\n/**\n * @title   GmxConfig\n * @dev     Used to store addresses and configuration values for the GMX system.\n * @notice  Ref stored in the regsitry, Only deployed on chains that support gmx\n */\n\ncontract GmxConfig {\n    IGmxRouter public immutable router;\n    IGmxPositionRouter public immutable positionRouter;\n    IGmxVault public immutable vault;\n    IGmxOrderBook public immutable orderBook;\n    bytes32 public immutable referralCode;\n    uint public immutable maxPositions = 2;\n    // The number of unexecuted requests a vault can have open at a time.\n    uint public immutable maxOpenRequests = 2;\n    // The number of unexecuted decrease orders a vault can have open at a time.\n    uint public immutable maxOpenDecreaseOrders = 2;\n    uint public immutable acceptablePriceDeviationBasisPoints = 200; // 2%\n\n    constructor(\n        address _gmxRouter,\n        address _gmxPositionRouter,\n        address _gmxVault,\n        address _gmxOrderBook,\n        bytes32 _gmxReferralCode\n    ) {\n        router = IGmxRouter(_gmxRouter);\n        positionRouter = IGmxPositionRouter(_gmxPositionRouter);\n        vault = IGmxVault(_gmxVault);\n        orderBook = IGmxOrderBook(_gmxOrderBook);\n        referralCode = _gmxReferralCode;\n    }\n}\n"
      },
      "contracts/integration-data-tracker/IntegrationDataTracker.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nimport { IntegrationDataTrackerStorage, Integration } from './IntegrationDataTrackerStorage.sol';\n\n// This contract is a general store for when we need to store data that is relevant to an integration\n// For example with GMX we must track what positions are open for each vault\n\ncontract IntegrationDataTracker {\n    /**\n     * @notice record new raw data\n     * @param _integration used as the namespace for the data\n     * @param _data the data track data to be recorded in storage\n     */\n    function pushData(Integration _integration, bytes memory _data) external {\n        _pushData(_integration, msg.sender, _data);\n    }\n\n    /**\n     * @notice record new raw data\n     * @param _integration used as the namespace for the data\n     * @param _data the data track data to be recorded in storage\n     */\n    function pushData(bytes32 _integration, bytes memory _data) external {\n        _pushData(_integration, msg.sender, _data);\n    }\n\n    /**\n     * @notice delete data\n     * @param _integration used as the namespace for the data\n     * @param _index data index to be removed from storage\n     */\n    function removeData(Integration _integration, uint256 _index) external {\n        _removeData(_integration, msg.sender, _index);\n    }\n\n    /**\n     * @notice delete data\n     * @param _integration used as the namespace for the data\n     * @param _index data index to be removed from storage\n     */\n    function removeData(bytes32 _integration, uint256 _index) external {\n        _removeData(_integration, msg.sender, _index);\n    }\n\n    /**\n     * @notice returns tracked data by index\n     * @param _integration used as the namespace for the data\n     * @param _vault the vaultAddress\n     * @param _index the index of data track data\n     * @return data the data track data of given NFT_TYPE & poolLogic & index\n     */\n    function getData(\n        Integration _integration,\n        address _vault,\n        uint256 _index\n    ) external view returns (bytes memory) {\n        return\n            IntegrationDataTrackerStorage.layout().trackedData[\n                bytes32(uint(_integration))\n            ][_vault][_index];\n    }\n\n    /**\n     * @notice returns tracked data by index\n     * @param _integration used as the namespace for the data\n     * @param _vault the vaultAddress\n     * @param _index the index of data track data\n     * @return data the data track data of given NFT_TYPE & poolLogic & index\n     */\n    function getData(\n        bytes32 _integration,\n        address _vault,\n        uint256 _index\n    ) external view returns (bytes memory) {\n        return\n            IntegrationDataTrackerStorage.layout().trackedData[_integration][\n                _vault\n            ][_index];\n    }\n\n    /**\n     * @notice returns all tracked datas by NFT_TYPE & poolLogic\n     * @param _integration used as the namespace for the data\n     * @param _vault the vaultAddress\n     * @return data all tracked datas of given NFT_TYPE & poolLogic\n     */\n    function getAllData(\n        Integration _integration,\n        address _vault\n    ) external view returns (bytes[] memory) {\n        return\n            IntegrationDataTrackerStorage.layout().trackedData[\n                bytes32(uint(_integration))\n            ][_vault];\n    }\n\n    /**\n     * @notice returns all tracked datas by NFT_TYPE & poolLogic\n     * @param _integration used as the namespace for the data\n     * @param _vault the vaultAddress\n     * @return data all tracked datas of given NFT_TYPE & poolLogic\n     */\n    function getAllData(\n        bytes32 _integration,\n        address _vault\n    ) external view returns (bytes[] memory) {\n        return\n            IntegrationDataTrackerStorage.layout().trackedData[_integration][\n                _vault\n            ];\n    }\n\n    /**\n     * @notice returns all tracked datas by NFT_TYPE & poolLogic\n     * @param _integration used as the namespace for the data\n     * @param _vault the vaultAddress\n     * @return count all tracked datas count of given NFT_TYPE & poolLogic\n     */\n    function getDataCount(\n        Integration _integration,\n        address _vault\n    ) external view returns (uint256) {\n        return\n            IntegrationDataTrackerStorage\n            .layout()\n            .trackedData[bytes32(uint(_integration))][_vault].length;\n    }\n\n    /**\n     * @notice returns all tracked datas by NFT_TYPE & poolLogic\n     * @param _integration used as the namespace for the data\n     * @param _vault the vaultAddress\n     * @return count all tracked datas count of given NFT_TYPE & poolLogic\n     */\n    function getDataCount(\n        bytes32 _integration,\n        address _vault\n    ) external view returns (uint256) {\n        return\n            IntegrationDataTrackerStorage\n            .layout()\n            .trackedData[_integration][_vault].length;\n    }\n\n    /**\n     * @notice record new raw data\n     * @param _integration used as the namespace for the data\n     * @param _vault the vaultAddress\n     * @param _data the data track data to be recorded in storage\n     */\n    function _pushData(\n        bytes32 _integration,\n        address _vault,\n        bytes memory _data\n    ) private {\n        IntegrationDataTrackerStorage\n        .layout()\n        .trackedData[_integration][_vault].push(_data);\n    }\n\n    /**\n     * @notice record new raw data\n     * @param _integration used as the namespace for the data\n     * @param _vault the vaultAddress\n     * @param _data the data track data to be recorded in storage\n     */\n    function _pushData(\n        Integration _integration,\n        address _vault,\n        bytes memory _data\n    ) private {\n        IntegrationDataTrackerStorage\n        .layout()\n        .trackedData[bytes32(uint(_integration))][_vault].push(_data);\n    }\n\n    /**\n     * @notice delete data\n     * @param _integration used as the namespace for the data\n     * @param _vault the vaultAddress\n     * @param _index data index to be removed from storage\n     */\n    function _removeData(\n        bytes32 _integration,\n        address _vault,\n        uint256 _index\n    ) private {\n        IntegrationDataTrackerStorage.Layout\n            storage l = IntegrationDataTrackerStorage.layout();\n        uint256 length = l.trackedData[_integration][_vault].length;\n        require(_index < length, 'invalid index');\n\n        l.trackedData[_integration][_vault][_index] = l.trackedData[\n            _integration\n        ][_vault][length - 1];\n        l.trackedData[_integration][_vault].pop();\n    }\n\n    /**\n     * @notice delete data\n     * @param _integration used as the namespace for the data\n     * @param _vault the vaultAddress\n     * @param _index data index to be removed from storage\n     */\n    function _removeData(\n        Integration _integration,\n        address _vault,\n        uint256 _index\n    ) private {\n        IntegrationDataTrackerStorage.Layout\n            storage l = IntegrationDataTrackerStorage.layout();\n        bytes32 key = bytes32(uint(_integration));\n        uint256 length = l.trackedData[key][_vault].length;\n        require(_index < length, 'invalid index');\n\n        l.trackedData[key][_vault][_index] = l.trackedData[key][_vault][\n            length - 1\n        ];\n        l.trackedData[key][_vault].pop();\n    }\n}\n"
      },
      "contracts/integration-data-tracker/IntegrationDataTrackerStorage.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\n// Not sure if we should use an enum here because the integrations are not fixed\n// We could use a keccak(\"IntegrationName\") instead, this contract will have to be upgraded if we add a new integration\n// Because solidity validates enum params at runtime\nenum Integration {\n    GMXRequests,\n    GMXPositions,\n    GMXDecreaseOrders\n}\n\nlibrary IntegrationDataTrackerStorage {\n    bytes32 internal constant STORAGE_SLOT =\n        keccak256('valio.storage.IntegationDataTracker');\n\n    // solhint-disable-next-line ordering\n    struct Layout {\n        // Integration -> vault -> data[]\n        mapping(bytes32 => mapping(address => bytes[])) trackedData;\n    }\n\n    function layout() internal pure returns (Layout storage l) {\n        bytes32 slot = STORAGE_SLOT;\n\n        assembly {\n            l.slot := slot\n        }\n    }\n}\n"
      },
      "contracts/interfaces/IAggregatorV3Interface.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\ninterface IAggregatorV3Interface {\n    function description() external view returns (string memory);\n\n    function decimals() external view returns (uint8);\n\n    function latestRoundData()\n        external\n        view\n        returns (\n            uint80 roundId,\n            int256 answer,\n            uint256 startedAt,\n            uint256 updatedAt,\n            uint80 answeredInRound\n        );\n}\n"
      },
      "contracts/interfaces/IGmxOrderBook.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\n// solhint-disable ordering\ninterface IGmxOrderBook {\n    function minExecutionFee() external view returns (uint256);\n\n    function decreaseOrdersIndex(address) external view returns (uint256);\n\n    function getSwapOrder(\n        address _account,\n        uint256 _orderIndex\n    )\n        external\n        view\n        returns (\n            address path0,\n            address path1,\n            address path2,\n            uint256 amountIn,\n            uint256 minOut,\n            uint256 triggerRatio,\n            bool triggerAboveThreshold,\n            bool shouldUnwrap,\n            uint256 executionFee\n        );\n\n    function getIncreaseOrder(\n        address _account,\n        uint256 _orderIndex\n    )\n        external\n        view\n        returns (\n            address purchaseToken,\n            uint256 purchaseTokenAmount,\n            address collateralToken,\n            address indexToken,\n            uint256 sizeDelta,\n            bool isLong,\n            uint256 triggerPrice,\n            bool triggerAboveThreshold,\n            uint256 executionFee\n        );\n\n    function getDecreaseOrder(\n        address _account,\n        uint256 _orderIndex\n    )\n        external\n        view\n        returns (\n            address collateralToken,\n            uint256 collateralDelta,\n            address indexToken,\n            uint256 sizeDelta,\n            bool isLong,\n            uint256 triggerPrice,\n            bool triggerAboveThreshold,\n            uint256 executionFee\n        );\n\n    function executeSwapOrder(address, uint256, address payable) external;\n\n    function executeDecreaseOrder(address, uint256, address payable) external;\n\n    function executeIncreaseOrder(address, uint256, address payable) external;\n\n    function createDecreaseOrder(\n        address _indexToken,\n        uint256 _sizeDelta,\n        address _collateralToken,\n        uint256 _collateralDelta,\n        bool _isLong,\n        uint256 _triggerPrice,\n        bool _triggerAboveThreshold\n    ) external payable;\n\n    function updateDecreaseOrder(\n        uint256 _orderIndex,\n        uint256 _collateralDelta,\n        uint256 _sizeDelta,\n        uint256 _triggerPrice,\n        bool _triggerAboveThreshold\n    ) external;\n\n    function cancelDecreaseOrder(uint256 _orderIndex) external;\n}\n"
      },
      "contracts/interfaces/IGmxPositionRouter.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\n// solhint-disable ordering\ninterface IGmxPositionRouter {\n    struct IncreasePositionRequest {\n        address account;\n        address[] path;\n        address indexToken;\n        uint256 amountIn;\n        uint256 minOut;\n        uint256 sizeDelta;\n        bool isLong;\n        uint256 acceptablePrice;\n        uint256 executionFee;\n        uint256 blockNumber;\n        uint256 blockTime;\n        bool hasCollateralInETH;\n        address callbackTarget;\n    }\n\n    struct DecreasePositionRequest {\n        address account;\n        address[] path;\n        address indexToken;\n        uint256 collateralDelta;\n        uint256 sizeDelta;\n        bool isLong;\n        address receiver;\n        uint256 acceptablePrice;\n        uint256 minOut;\n        uint256 executionFee;\n        uint256 blockNumber;\n        uint256 blockTime;\n        bool withdrawETH;\n        address callbackTarget;\n    }\n\n    function setPositionKeeper(address _account, bool _isActive) external;\n\n    function executeIncreasePosition(\n        bytes32 _key,\n        address payable _executionFeeReceiver\n    ) external returns (bool);\n\n    function executeDecreasePosition(\n        bytes32 _key,\n        address payable _executionFeeReceiver\n    ) external returns (bool);\n\n    function createIncreasePosition(\n        address[] memory _path,\n        address _indexToken,\n        uint256 _amountIn,\n        uint256 _minOut,\n        uint256 _sizeDelta,\n        bool _isLong,\n        uint256 _acceptablePrice,\n        uint256 _executionFee,\n        bytes32 _referralCode,\n        address _callbackTarget\n    ) external payable returns (bytes32);\n\n    function createDecreasePosition(\n        address[] memory _path,\n        address _indexToken,\n        uint256 _collateralDelta,\n        uint256 _sizeDelta,\n        bool _isLong,\n        address _receiver,\n        uint256 _acceptablePrice,\n        uint256 _minOut,\n        uint256 _executionFee,\n        bool _withdrawETH,\n        address _callbackTarget\n    ) external payable returns (bytes32);\n\n    function minExecutionFee() external view returns (uint256);\n\n    function getRequestKey(\n        address _account,\n        uint256 _index\n    ) external pure returns (bytes32);\n\n    function cancelIncreasePosition(\n        bytes32 _key,\n        address payable _executionFeeReceiver\n    ) external returns (bool);\n\n    function cancelDecreasePosition(\n        bytes32 _key,\n        address payable _executionFeeReceiver\n    ) external returns (bool);\n\n    function executeIncreasePositions(\n        uint256 _count,\n        address payable _executionFeeReceiver\n    ) external;\n\n    function executeDecreasePositions(\n        uint256 _count,\n        address payable _executionFeeReceiver\n    ) external;\n\n    function increasePositionRequestKeysStart() external view returns (uint256);\n\n    function decreasePositionRequestKeysStart() external view returns (uint256);\n\n    function increasePositionsIndex(\n        address account\n    ) external view returns (uint256);\n\n    function increasePositionRequests(\n        bytes32 key\n    )\n        external\n        view\n        returns (\n            address account,\n            // address[] memory path,\n            address indexToken,\n            uint256 amountIn,\n            uint256 minOut,\n            uint256 sizeDelta,\n            bool isLong,\n            uint256 acceptablePrice,\n            uint256 executionFee,\n            uint256 blockNumber,\n            uint256 blockTime,\n            bool hasCollateralInETH,\n            address callbackTarget\n        );\n\n    function getIncreasePositionRequestPath(\n        bytes32 _key\n    ) external view returns (address[] memory);\n\n    function getDecreasePositionRequestPath(\n        bytes32 _key\n    ) external view returns (address[] memory);\n\n    function decreasePositionsIndex(\n        address account\n    ) external view returns (uint256);\n\n    function vault() external view returns (address);\n\n    function admin() external view returns (address);\n\n    function getRequestQueueLengths()\n        external\n        view\n        returns (uint256, uint256, uint256, uint256);\n\n    function decreasePositionRequests(\n        bytes32\n    )\n        external\n        view\n        returns (\n            address account,\n            address indexToken,\n            uint256 collateralDelta,\n            uint256 sizeDelta,\n            bool isLong,\n            address receiver,\n            uint256 acceptablePrice,\n            uint256 minOut,\n            uint256 executionFee,\n            uint256 blockNumber,\n            uint256 blockTime,\n            bool withdrawETH,\n            address callbackTarget\n        );\n}\n"
      },
      "contracts/interfaces/IGmxPositionRouterCallbackReceiver.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\ninterface IGmxPositionRouterCallbackReceiver {\n    function gmxPositionCallback(\n        bytes32 positionKey,\n        bool isExecuted,\n        bool isIncrease\n    ) external;\n}\n"
      },
      "contracts/interfaces/IGmxRouter.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\ninterface IGmxRouter {\n    function addPlugin(address _plugin) external;\n\n    function pluginTransfer(\n        address _token,\n        address _account,\n        address _receiver,\n        uint256 _amount\n    ) external;\n\n    function pluginIncreasePosition(\n        address _account,\n        address _collateralToken,\n        address _indexToken,\n        uint256 _sizeDelta,\n        bool _isLong\n    ) external;\n\n    function pluginDecreasePosition(\n        address _account,\n        address _collateralToken,\n        address _indexToken,\n        uint256 _collateralDelta,\n        uint256 _sizeDelta,\n        bool _isLong,\n        address _receiver\n    ) external returns (uint256);\n\n    function swap(\n        address[] memory _path,\n        uint256 _amountIn,\n        uint256 _minOut,\n        address _receiver\n    ) external;\n\n    function directPoolDeposit(address _token, uint256 _amount) external;\n\n    function approvePlugin(address) external;\n\n    function decreasePosition(\n        address _collateralToken,\n        address _indexToken,\n        uint256 _collateralDelta,\n        uint256 _sizeDelta,\n        bool _isLong,\n        address _receiver,\n        uint256 _price\n    ) external;\n\n    function swapETHToTokens(\n        address[] memory _path,\n        uint256 _minOut,\n        address _receiver\n    ) external payable;\n}\n"
      },
      "contracts/interfaces/IGmxVault.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n// solhint-disable ordering\ninterface IGmxVault {\n    function maxGasPrice() external view returns (uint256);\n\n    function approvedRouters(\n        address _account,\n        address _router\n    ) external view returns (bool);\n\n    function isLiquidator(address _account) external view returns (bool);\n\n    function isManager(address _account) external view returns (bool);\n\n    function minProfitBasisPoints(\n        address _token\n    ) external view returns (uint256);\n\n    function tokenBalances(address _token) external view returns (uint256);\n\n    function lastFundingTimes(address _token) external view returns (uint256);\n\n    function setLiquidator(address _liquidator, bool _isActive) external;\n\n    function setFundingRate(\n        uint256 _fundingInterval,\n        uint256 _fundingRateFactor,\n        uint256 _stableFundingRateFactor\n    ) external;\n\n    function updateCumulativeFundingRate(address _token) external;\n\n    function setFees(\n        uint256 _taxBasisPoints,\n        uint256 _stableTaxBasisPoints,\n        uint256 _mintBurnFeeBasisPoints,\n        uint256 _swapFeeBasisPoints,\n        uint256 _stableSwapFeeBasisPoints,\n        uint256 _marginFeeBasisPoints,\n        uint256 _liquidationFeeUsd,\n        uint256 _minProfitTime,\n        bool _hasDynamicFees\n    ) external;\n\n    function setTokenConfig(\n        address _token,\n        uint256 _tokenDecimals,\n        uint256 _redemptionBps,\n        uint256 _minProfitBps,\n        uint256 _maxUsdgAmount,\n        bool _isStable,\n        bool _isShortable\n    ) external;\n\n    function setPriceFeed(address _aggregatorAddress) external;\n\n    function withdrawFees(\n        address _token,\n        address _receiver\n    ) external returns (uint256);\n\n    function directPoolDeposit(address _token) external;\n\n    function buyUSDG(\n        address _token,\n        address _receiver\n    ) external returns (uint256);\n\n    function sellUSDG(\n        address _token,\n        address _receiver\n    ) external returns (uint256);\n\n    function swap(\n        address _tokenIn,\n        address _tokenOut,\n        address _receiver\n    ) external returns (uint256);\n\n    function increasePosition(\n        address _account,\n        address _collateralToken,\n        address _indexToken,\n        uint256 _sizeDelta,\n        bool _isLong\n    ) external;\n\n    function decreasePosition(\n        address _account,\n        address _collateralToken,\n        address _indexToken,\n        uint256 _collateralDelta,\n        uint256 _sizeDelta,\n        bool _isLong,\n        address _receiver\n    ) external returns (uint256);\n\n    function validateLiquidation(\n        address _account,\n        address _collateralToken,\n        address _indexToken,\n        bool _isLong,\n        bool _raise\n    ) external view returns (uint256, uint256);\n\n    function liquidatePosition(\n        address _account,\n        address _collateralToken,\n        address _indexToken,\n        bool _isLong,\n        address _feeReceiver\n    ) external;\n\n    function tokenToUsdMin(\n        address _token,\n        uint256 _tokenAmount\n    ) external view returns (uint256);\n\n    function usdToTokenMax(\n        address _token,\n        uint256 _usdAmount\n    ) external view returns (uint256);\n\n    function priceFeed() external view returns (address);\n\n    function fundingRateFactor() external view returns (uint256);\n\n    function stableFundingRateFactor() external view returns (uint256);\n\n    function cumulativeFundingRates(\n        address _token\n    ) external view returns (uint256);\n\n    function getNextFundingRate(address _token) external view returns (uint256);\n\n    function getFeeBasisPoints(\n        address _token,\n        uint256 _usdgDelta,\n        uint256 _feeBasisPoints,\n        uint256 _taxBasisPoints,\n        bool _increment\n    ) external view returns (uint256);\n\n    function liquidationFeeUsd() external view returns (uint256);\n\n    function taxBasisPoints() external view returns (uint256);\n\n    function stableTaxBasisPoints() external view returns (uint256);\n\n    function mintBurnFeeBasisPoints() external view returns (uint256);\n\n    function swapFeeBasisPoints() external view returns (uint256);\n\n    function stableSwapFeeBasisPoints() external view returns (uint256);\n\n    function marginFeeBasisPoints() external view returns (uint256);\n\n    function allWhitelistedTokensLength() external view returns (uint256);\n\n    function allWhitelistedTokens(uint256) external view returns (address);\n\n    function whitelistedTokens(address _token) external view returns (bool);\n\n    function stableTokens(address _token) external view returns (bool);\n\n    function shortableTokens(address _token) external view returns (bool);\n\n    function feeReserves(address _token) external view returns (uint256);\n\n    function globalShortSizes(address _token) external view returns (uint256);\n\n    function globalShortAveragePrices(\n        address _token\n    ) external view returns (uint256);\n\n    function maxGlobalShortSizes(\n        address _token\n    ) external view returns (uint256);\n\n    function tokenDecimals(address _token) external view returns (uint256);\n\n    function tokenWeights(address _token) external view returns (uint256);\n\n    function guaranteedUsd(address _token) external view returns (uint256);\n\n    function poolAmounts(address _token) external view returns (uint256);\n\n    function bufferAmounts(address _token) external view returns (uint256);\n\n    function reservedAmounts(address _token) external view returns (uint256);\n\n    function usdgAmounts(address _token) external view returns (uint256);\n\n    function maxUsdgAmounts(address _token) external view returns (uint256);\n\n    function getRedemptionAmount(\n        address _token,\n        uint256 _usdgAmount\n    ) external view returns (uint256);\n\n    function getMaxPrice(address _token) external view returns (uint256);\n\n    function getMinPrice(address _token) external view returns (uint256);\n\n    function getDelta(\n        address _indexToken,\n        uint256 _size,\n        uint256 _averagePrice,\n        bool _isLong,\n        uint256 _lastIncreasedTime\n    ) external view returns (bool, uint256);\n\n    function getPositionDelta(\n        address _account,\n        address _collateralToken,\n        address _indexToken,\n        bool _isLong\n    ) external view returns (bool, uint256);\n\n    function getPositionKey(\n        address _account,\n        address _collateralToken,\n        address _indexToken,\n        bool _isLong\n    ) external pure returns (bytes32);\n\n    function getPosition(\n        address _account,\n        address _collateralToken,\n        address _indexToken,\n        bool _isLong\n    )\n        external\n        view\n        returns (\n            uint256 size,\n            uint256 collateral,\n            uint256 averagePrice,\n            uint256 entryFundingRate,\n            uint256 reserveAmount,\n            uint256 realisedPnl,\n            bool hasRealisedProfit,\n            uint256 lastIncreasedTime\n        );\n\n    function getFundingFee(\n        address _token,\n        uint256 _size,\n        uint256 _entryFundingRate\n    ) external view returns (uint256);\n\n    function getPositionFee(uint256 _sizeDelta) external view returns (uint256);\n\n    function PRICE_PRECISION() external view returns (uint256);\n\n    function BASIS_POINTS_DIVISOR() external view returns (uint256);\n\n    function setError(uint256 _errorCode, string calldata _error) external;\n\n    function isInitialized() external view returns (bool);\n\n    function isSwapEnabled() external view returns (bool);\n\n    function isLeverageEnabled() external view returns (bool);\n\n    function router() external view returns (address);\n\n    function usdg() external view returns (address);\n\n    function gov() external view returns (address);\n\n    function whitelistedTokenCount() external view returns (uint256);\n\n    function maxLeverage() external view returns (uint256);\n\n    function minProfitTime() external view returns (uint256);\n\n    function hasDynamicFees() external view returns (bool);\n\n    function fundingInterval() external view returns (uint256);\n\n    function totalTokenWeights() external view returns (uint256);\n\n    function getTargetUsdgAmount(\n        address _token\n    ) external view returns (uint256);\n\n    function inManagerMode() external view returns (bool);\n\n    function inPrivateLiquidationMode() external view returns (bool);\n}\n"
      },
      "contracts/interfaces/ISnxAddressResolver.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface ISnxAddressResolver {\n    function importAddresses(\n        bytes32[] calldata names,\n        address[] calldata destinations\n    ) external;\n\n    function rebuildCaches(address[] calldata destinations) external;\n\n    function owner() external view returns (address);\n\n    function getSynth(bytes32 key) external view returns (address);\n\n    function getAddress(bytes32 name) external view returns (address);\n}\n"
      },
      "contracts/interfaces/IWeth.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\ninterface IWETH {\n    function deposit() external payable;\n\n    function withdraw(uint256 wad) external;\n\n    function approve(address guy, uint256 wad) external returns (bool);\n\n    function transfer(address dst, uint256 wad) external returns (bool);\n\n    function balanceOf(address user) external view returns (uint256);\n}\n"
      },
      "contracts/lib/Call.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\n/**\n * @title   Call\n * @dev     Utils for making calls to other contracts that bubble up the revert reason\n */\n\nlibrary Call {\n    function _delegate(address to, bytes memory data) internal {\n        (bool success, bytes memory result) = to.delegatecall(data);\n\n        if (!success) {\n            if (result.length < 68) revert();\n            assembly {\n                result := add(result, 0x04)\n            }\n            revert(abi.decode(result, (string)));\n        }\n    }\n\n    function _call(address to, bytes memory data) internal {\n        (bool success, bytes memory result) = to.call(data);\n\n        if (!success) {\n            if (result.length < 68) revert('call failed');\n            assembly {\n                result := add(result, 0x04)\n            }\n            revert(abi.decode(result, (string)));\n        }\n    }\n}\n"
      },
      "contracts/lib/Constants.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nlibrary Constants {\n    // Aka decimals, the precision of the numbers the vault returns`\n    uint internal constant VAULT_PRECISION = 10 ** 8;\n    // Used for dealing with percentages\n    uint internal constant BASIS_POINTS_DIVISOR = 10_000;\n    // Used for dealing with portions of a whole where we must have high accuracy\n    uint internal constant PORTION_DIVISOR = 10 ** 18;\n}\n"
      },
      "contracts/lib/TrustlessPermit.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\nimport { IERC20 } from '@solidstate/contracts/interfaces/IERC20.sol';\nimport { SafeERC20 } from '@solidstate/contracts/utils/SafeERC20.sol';\nimport { IERC2612 } from '@solidstate/contracts/token/ERC20/permit/IERC2612.sol';\n\n/**\n * @title   TrustlessPermit\n * @dev     Signed Permits can be extracted and front run. Meaning that they will revert if already used\n * @dev     Can be a very unlikely griefing vector. This library mitigates this by trying permit() first\n * @notice  Credit to https://www.trust-security.xyz/\n */\n\nlibrary TrustlessPermit {\n    function trustlessPermit(\n        address token,\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal {\n        // Try permit() before allowance check to advance nonce if possible\n        try IERC2612(token).permit(owner, spender, value, deadline, v, r, s) {\n            return;\n        } catch {\n            // Permit potentially got frontran. Continue anyways if allowance is sufficient.\n            if (IERC20(token).allowance(owner, spender) >= value) {\n                return;\n            }\n        }\n        revert('Permit failure');\n    }\n}\n"
      },
      "contracts/redeemers/IRedeemer.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nimport { IRedeemerEvents } from './IRedeemerEvents.sol';\n\n/**\n * @title   IRedeemer\n * @dev     Interface for redeeming assets from a vault\n * @notice  The redeemers are responsible for transferring assets to the withdrawer\n */\n\ninterface IRedeemer is IRedeemerEvents {\n    // For some assets, closing a portion directly to the user is not possible\n    // Or some assets only allow the claiming all rewards to the owner (you can't claim a portion of the rewards)\n    // In this case these operations have to happen first, returning those assets to the vault\n    // And then being distributed to the withdrawer during normal erc20 withdraw processing\n    // A good example of this is with GMX, where sometimes we will have to close the entire position to the vault\n    // And then distribute a portion of the proceeds downstream to the withdrawer.\n    // The function of having preWithdraw saves us the drama of having to try and ORDER asset withdraws.\n    function preWithdraw(\n        uint tokenId,\n        address asset,\n        address withdrawer,\n        uint portion\n    ) external payable;\n\n    function withdraw(\n        uint tokenId,\n        address asset,\n        address withdrawer,\n        uint portion\n    ) external payable;\n\n    function hasPreWithdraw() external view returns (bool);\n}\n"
      },
      "contracts/redeemers/IRedeemerEvents.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\ninterface IRedeemerEvents {\n    event Redeemed(\n        uint tokenId,\n        address indexed asset,\n        address to,\n        address redeemedAs,\n        uint amount\n    );\n}\n"
      },
      "contracts/registry/Registry.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\nimport { Accountant } from '../Accountant.sol';\nimport { ExecutorIntegration } from '../executors/IExecutor.sol';\nimport { IntegrationDataTracker } from '../integration-data-tracker/IntegrationDataTracker.sol';\nimport { RegistryStorage } from './RegistryStorage.sol';\nimport { GmxConfig } from '../GmxConfig.sol';\nimport { SnxConfig } from '../SnxConfig.sol';\nimport { Transport } from '../transport/Transport.sol';\nimport { Constants } from '../lib/Constants.sol';\nimport { VaultRiskProfile } from '../vault-base/IVaultRiskProfile.sol';\nimport { SafeOwnable } from '@solidstate/contracts/access/ownable/SafeOwnable.sol';\nimport { IWETH } from '../interfaces/IWeth.sol';\nimport { IAggregatorV3Interface } from '../interfaces/IAggregatorV3Interface.sol';\nimport { IValioCustomAggregator } from '../aggregators/IValioCustomAggregator.sol';\n\nimport { Pausable } from '@solidstate/contracts/security/pausable/Pausable.sol';\nimport { IUniswapV3Pool } from '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\n\n/**\n * @title   Registry\n * @dev     This contract is cut into the RegistryDiamond.\n * @notice  The registry is a central place to store all the addresses and settings in the system.\n */\n\ncontract Registry is SafeOwnable, Pausable {\n    // Emit event that informs that the another event was emitted on the target address\n    // This means we can listen to this event and know that the target address has emitted an event\n    event EventEmitted(address target);\n\n    event AssetTypeChanged(address asset, RegistryStorage.AssetType assetType);\n    event AssetDeprecationChanged(address asset, bool deprecated);\n    event AssetHardDeprecationChanged(address asset, bool deprecated);\n\n    modifier onlyTransport() {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        require(address(l.transport) == msg.sender, 'not transport');\n        _;\n    }\n\n    modifier onlyVault() {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        require(\n            l.parentVaults[msg.sender] || l.childVaults[msg.sender],\n            'not vault'\n        );\n        _;\n    }\n\n    /**\n     * @notice  Initializes the registry with the initial settings\n     * @dev     DEPRECATED: use individual setters\n     * @param   _chainId  The LayerZero chainId of the chain the registry is deployed to\n     * @param   _protocolTreasury The address of the protocol treasury\n     * @param   _transport  The address of the transport contract\n     * @param   _parentVaultDiamond  The address of the parent vault diamond\n     * @param   _childVaultDiamond  The address of the child vault diamond\n     * @param   _accountant  The address of the accountant\n     * @param   _integrationDataTracker  The address of the integration data tracker\n     */\n    function initialize(\n        uint16 _chainId,\n        address _protocolTreasury,\n        address payable _transport,\n        address _parentVaultDiamond,\n        address _childVaultDiamond,\n        address _accountant,\n        address _integrationDataTracker\n    ) external onlyOwner {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        require(l.chainId == 0, 'Already initialized');\n        l.chainId = _chainId;\n        l.protocolTreasury = _protocolTreasury;\n        l.transport = Transport(_transport);\n        l.parentVaultDiamond = _parentVaultDiamond;\n        l.childVaultDiamond = _childVaultDiamond;\n        l.accountant = Accountant(_accountant);\n        l.integrationDataTracker = IntegrationDataTracker(\n            _integrationDataTracker\n        );\n        l.chainlinkTimeout = 24 hours;\n    }\n\n    /// MODIFIERS\n\n    /**\n     * @notice  Emit event that informs that the another event was emitted on the caller address\n     * @dev     This means we can listen to this event and know that the target address has emitted an event\n     */\n    function emitEvent() external {\n        _emitEvent(msg.sender);\n    }\n\n    /**\n     * @notice  Pauses the Protocol\n     * @dev     Can only be called by the owner\n     * @dev     Will block deposits and withdraws amoung other things\n     */\n    function pause() external onlyOwner {\n        _pause();\n    }\n\n    /**\n     * @notice  Unpauses the Protocol\n     */\n    function unpause() external onlyOwner {\n        _unpause();\n    }\n\n    /**\n     * @notice  Allows the transport to add a vault to the registry\n     * @dev     The creation of Vaults should be moved to the Registry\n     * @param   vault The address of the vault to add\n     */\n    function addVaultParent(address vault) external onlyTransport {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        l.parentVaults[vault] = true;\n        l.parentVaultList.push(vault);\n    }\n\n    /**\n     * @notice  Allows the transport to add a child vault to the registry\n     * @dev     The creation of Vaults should be moved to the Registry\n     * @param   vault  The address of the vault to add\n     */\n    function addVaultChild(address vault) external onlyTransport {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        l.childVaults[vault] = true;\n        l.childVaultList.push(vault);\n    }\n\n    /**\n     * @notice  Sets the given asset to deprecated/undeprecated\n     * @dev     Deprecated assets are not allowed to be traded into\n     * @param   asset  The address of the asset to deprecate\n     * @param   deprecated  True if the asset is deprecated\n     */\n    function setDeprecatedAsset(\n        address asset,\n        bool deprecated\n    ) external onlyOwner {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        l.deprecatedAssets[asset] = deprecated;\n        emit AssetDeprecationChanged(asset, deprecated);\n        _emitEvent(address(this));\n    }\n\n    /**\n     * @notice  Sets the given asset to hard deprecated/undeprecated\n     * @dev     Hard deprecated assets cannot be valued, vaults holding them cannot be deposited into\n     * @param   asset  The address of the asset to deprecate\n     * @param   deprecated  True if the asset is deprecated\n     */\n    function setHardDeprecatedAsset(\n        address asset,\n        bool deprecated\n    ) external onlyOwner {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        l.hardDeprecatedAssets[asset] = deprecated;\n        emit AssetHardDeprecationChanged(asset, deprecated);\n        _emitEvent(address(this));\n    }\n\n    /**\n     * @notice  Sets the asset type for the given asset\n     * @dev     Erc20, GMX, SnxPerpsV2, etc\n     * @param   asset  The address of the asset\n     * @param   _assetType  The type of the asset\n     */\n    function setAssetType(\n        address asset,\n        RegistryStorage.AssetType _assetType\n    ) external onlyOwner {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        l.assetTypes[asset] = _assetType;\n        l.assetList.push(asset);\n        emit AssetTypeChanged(asset, _assetType);\n        _emitEvent(address(this));\n    }\n\n    /**\n     * @notice  Sets the Valuer Contract for the given AssetType\n     * @dev     The valuer is responsible for getting the value of the asset\n     * @param   _assetType  The type of the asset\n     * @param   valuer  The address of the valuer contract\n     */\n    function setValuer(\n        RegistryStorage.AssetType _assetType,\n        address valuer\n    ) external onlyOwner {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        l.valuers[_assetType] = valuer;\n    }\n\n    /**\n     * @notice  Sets the Redeemer Contract for the given AssetType\n     * @dev     The redeemer is responsible for redeeming the asset from the vault\n     * @param   _assetType  The type of the asset\n     * @param   redeemer  The address of the redeemer contract\n     */\n    function setRedeemer(\n        RegistryStorage.AssetType _assetType,\n        address redeemer\n    ) external onlyOwner {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        l.redeemers[_assetType] = redeemer;\n    }\n\n    /**\n     * @notice  Sets the Chainlink Aggregator for the given asset\n     * @dev     The aggregator is responsible for getting the price of the asset\n     * @dev     Not all assets have a chainlink aggregator, gmx for instance returns a value in usd.\n     * @param   asset  The address of the asset\n     * @param   aggregator  The address of the chainlink aggregator\n     */\n    function setChainlinkV3USDAggregator(\n        address asset,\n        IAggregatorV3Interface aggregator\n    ) external onlyOwner {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        l.chainlinkV3USDAggregators[asset] = aggregator;\n    }\n\n    /**\n     * @notice  Sets the Aggregator Contract for the given AggregatorType\n     * @dev     AggregatorType eg: UniswapV3Twap,VelodromeV2Twap\n     * @dev     It will be called to get/calculate the unit price for any assets configured with this AggregatorType\n     * @param   _aggregatorType  The type of the aggregator\n     * @param   _customAggregator The address of the aggregator contract\n     */\n    function setValioCustomUSDAggregator(\n        RegistryStorage.AggregatorType _aggregatorType,\n        IValioCustomAggregator _customAggregator\n    ) external onlyOwner {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        l.valioCustomUSDAggregators[_aggregatorType] = _customAggregator;\n    }\n\n    /**\n     * @notice  Sets Aggregator Type for the given asset\n     * @dev     The AggregatorType will get the Aggregator that gets the price for the asset\n     * @dev     Havng `Aggregator` type allows us to share the same Aggregator for multiple assets\n     * @param   asset  The address of the asset\n     * @param   aggregatorType  The type of the aggregator\n     */\n    function setAssetAggregatorType(\n        address asset,\n        RegistryStorage.AggregatorType aggregatorType\n    ) external onlyOwner {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        l.assetAggregatorType[asset] = aggregatorType;\n    }\n\n    /**\n     * @notice  Sets the Accountant Contract\n     * @param   _accountant  The address of the accountant contract\n     */\n    function setAccountant(address _accountant) external onlyOwner {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        l.accountant = Accountant(_accountant);\n    }\n\n    /**\n     * @notice  Sets the Transport Contract\n     * @dev     The transport is proxy for all cross chain messaging\n     * @dev     Its a Diamond so should never change.\n     * @param   _transport The address of the transport contract\n     */\n    function setTransport(address payable _transport) external onlyOwner {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        l.transport = Transport(_transport);\n    }\n\n    /**\n     * @notice  Sets the protocol treasury address\n     * @dev     The protocol treasury is the address that receives the protocol fees\n     * @param   _treasury  The address of the protocol treasury\n     */\n    function setProtocolTreasury(address payable _treasury) external onlyOwner {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        l.protocolTreasury = (_treasury);\n    }\n\n    /**\n     * @notice  The protocols share of manager fees\n     * @param   _protocolFeeBips  The protocol fee in bips\n     */\n    function setProtocolFeeBips(uint256 _protocolFeeBips) external onlyOwner {\n        // 20% max fee\n        require(_protocolFeeBips <= 2000, 'invalid fee');\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        l.protocolFeeBips = _protocolFeeBips;\n    }\n\n    /**\n     * @notice  Sets the integration data tracker\n     * @dev     The integration data tracker is responsible for tracking the data from the integrations\n     * @dev     It should never change as the IntegrationDataTracker is a diamond. Changing it will loose stored state.\n     * @param   _integrationDataTracker  .\n     */\n    function setIntegrationDataTracker(\n        address _integrationDataTracker\n    ) external onlyOwner {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        l.integrationDataTracker = IntegrationDataTracker(\n            _integrationDataTracker\n        );\n    }\n\n    /**\n     * @notice  Sets the ZeroX Exchange Router\n     * @dev     Should be changed to use ancillaryContractAddresses\n     * @param   _zeroXExchangeRouter  The address of the ZeroX Exchange Router\n     */\n    function setZeroXExchangeRouter(\n        address _zeroXExchangeRouter\n    ) external onlyOwner {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        l.zeroXExchangeRouter = _zeroXExchangeRouter;\n    }\n\n    /**\n     * @notice  Sets the Executor for the given integration\n     * @dev     The executor is responsible for checking/executing manager transactions\n     * @param   integration The integration to set the executor for\n     * @param   executor  The address of the executor contract\n     */\n    function setExecutor(\n        ExecutorIntegration integration,\n        address executor\n    ) external onlyOwner {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        l.executors[integration] = executor;\n    }\n\n    /**\n     * @notice  Sets the deposit lockup time\n     * @dev     The deposit lockup time is the time that a deposit is locked up for.\n     * @dev     This protects lps from nefarious behaviour\n     * @param   _depositLockupTime  .\n     */\n    function setDepositLockupTime(uint _depositLockupTime) external onlyOwner {\n        require(\n            _depositLockupTime <= 24 hours && _depositLockupTime > 0,\n            'invalid lockup'\n        );\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        l.depositLockupTime = _depositLockupTime;\n    }\n\n    /**\n     * @notice  Sets the max active assets\n     * @dev     The max active assets is the maximum number of assets that can be active in a vault at any one time\n     * @dev     If the vault has to many assets it can exceed the block gas limit or make redemptions expensive (eth)\n     * @dev     This can vary from chain to chain\n     * @param   _maxActiveAssets The maximum number of active assets\n     */\n    function setMaxActiveAssets(uint _maxActiveAssets) external onlyOwner {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        l.maxActiveAssets = _maxActiveAssets;\n    }\n\n    /**\n     * @notice  Sets whether the manager can change the manager\n     * @dev     The manager can change the manager if this is true\n     * @param   _canChangeManager  True if the manager can change the manager\n     */\n    function setCanChangeManager(bool _canChangeManager) external onlyOwner {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        l.canChangeManager = _canChangeManager;\n    }\n\n    /**\n     * @notice  Sets the gmxConfig address\n     * @dev     Only for chains the support GMX\n     * @param   _gmxConfig  The address of the gmxConfig contract\n     */\n    function setGmxConfig(address _gmxConfig) external onlyOwner {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        l.gmxConfig = GmxConfig(_gmxConfig);\n    }\n\n    /**\n     * @notice  Sets the liveliness threshold\n     * @dev     The liveliness threshold is the time a vault value update from a child is valid for\n     * @param   _livelinessThreshold  The time in seconds\n     */\n    function setLivelinessThreshold(\n        uint256 _livelinessThreshold\n    ) external onlyOwner {\n        require(_livelinessThreshold <= 24 hours, 'invalid threshold');\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        l.livelinessThreshold = _livelinessThreshold;\n    }\n\n    /**\n     * @notice  Sets the max cpit bips\n     * @dev     The the maximum amount of cpit that is allowed in a 24 hour period for a given risk profile\n     * @param   riskProfile  The risk profile to set the max cpit bips for\n     * @param   _maxCpitBips  The maximum amount of cpit in bips\n     */\n    function setMaxCpitBips(\n        VaultRiskProfile riskProfile,\n        uint256 _maxCpitBips\n    ) external onlyOwner {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        l.maxCpitBips[riskProfile] = _maxCpitBips;\n    }\n\n    /**\n     * @notice  Sets the initial min deposit amount\n     * @dev     This is the minimum amount that has to be first deposited into a holding\n     * @param   _minDepositAmount The minimum deposit amount in USD (Constants.VAULT_PRECISION decimals)\n     */\n    function setMinDepositAmount(uint256 _minDepositAmount) external onlyOwner {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        l.minDepositAmount = _minDepositAmount;\n    }\n\n    /**\n     * @notice  Sets the default max deposit amount per holding\n     * @dev     This is the maximum amount that can be deposited into a holding\n     * @dev     If the vault has a custom value cap, this value is ignored\n     * @param   _maxDepositAmount The maximum deposit amount in USD (Constants.VAULT_PRECISION decimals)\n     */\n    function setMaxDepositAmount(uint256 _maxDepositAmount) external onlyOwner {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        l.maxDepositAmount = _maxDepositAmount;\n    }\n\n    /**\n     * @notice  Sets whether the manager can change the manager fees\n     * @param   _canChangeManagerFees  True if the manager can change the manager fees\n     */\n    function setCanChangeManagerFees(\n        bool _canChangeManagerFees\n    ) external onlyOwner {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        l.canChangeManagerFees = _canChangeManagerFees;\n    }\n\n    /**\n     * @notice  Sets whether the asset can be deposited into the vault\n     * @dev     Currently only USDC/USDC.e\n     * @dev     Only strong stablecoins should be added\n     * @param   _depositAsset The address of the asset\n     * @param   canDeposit    True if the asset can be deposited\n     */\n    function setDepositAsset(\n        address _depositAsset,\n        bool canDeposit\n    ) external onlyOwner {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        l.depositAssets[_depositAsset] = canDeposit;\n    }\n\n    /**\n     * @notice  Sets the vault value cap\n     * @dev     The default value cap for a vault\n     * @dev     Ignored if the vault has a custom value cap\n     * @param   _vaultValueCap The value cap in USD (Constants.VAULT_PRECISION decimals)\n     */\n    function setVaultValueCap(uint256 _vaultValueCap) external onlyOwner {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        l.vaultValueCap = _vaultValueCap;\n    }\n\n    /**\n     * @notice  Sets the withdraw automator\n     * @dev     DEPRECATED: Use Relay\n     * @param   _withdrawAutomator The address of the withdraw automator\n     */\n    function setWithdrawAutomator(\n        address _withdrawAutomator\n    ) external onlyOwner {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        l.withdrawAutomator = _withdrawAutomator;\n    }\n\n    /**\n     * @notice  Sets the deposit automator\n     * @dev     DEPRECATED: Use Relay\n     * @param   _depositAutomator  The address of the deposit automator\n     */\n    function setDepositAutomator(address _depositAutomator) external onlyOwner {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        l.depositAutomator = _depositAutomator;\n    }\n\n    /**\n     * @notice  Sets the snxConfig address\n     * @dev     Only for chains the support SNX\n     * @param   _snxConfig  The address of the snxConfig contract\n     */\n    function setSnxConfig(address _snxConfig) external onlyOwner {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        l.snxConfig = SnxConfig(_snxConfig);\n    }\n\n    /**\n     * @notice  Sets the snxPerpsV2Erc20WrapperDiamond\n     * @dev     A snxPerpsV2Erc20Wrapper is deployed for each snx perp position in a vault\n     * @param   _snxPerpsV2Erc20WrapperDiamond  The implementation for a SnxPerpsV2Erc20Wrapper\n     */\n    function setSnxPerpsV2Erc20WrapperDiamond(\n        address _snxPerpsV2Erc20WrapperDiamond\n    ) external onlyOwner {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        l.snxPerpsV2Erc20WrapperDiamond = _snxPerpsV2Erc20WrapperDiamond;\n    }\n\n    /**\n     * @notice  Sets a custom value cap for a vault\n     * @dev     Once a vault exceeds this value, it will not accept any more deposits\n     * @param   vault  The address of the vault\n     * @param   _customVaultValueCap  The custom value cap in USD (Constants.VAULT_PRECISION decimals)\n     */\n    function setCustomVaultValueCap(\n        address vault,\n        uint256 _customVaultValueCap\n    ) external onlyOwner {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        l.customVaultValueCaps[vault] = _customVaultValueCap;\n    }\n\n    /**\n     * @notice  Adds a snxPerpsV2Erc20Wrapper to the registry\n     * @dev     Allows us to store All wrappers for offchain use/tracking\n     * @param   wrapperAddress  The address of the snxPerpsV2Erc20Wrapper\n     */\n    function addSnxPerpsV2Erc20Wrapper(\n        address wrapperAddress\n    ) external onlyVault {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        l.snxPerpsV2Erc20WrapperList.push(wrapperAddress);\n    }\n\n    /**\n     * @notice  Sets the uniswap v3Pool for the given asset\n     * @dev     We store this information in the registry so if we need to upate the logic of the UniswapV3Twap we can\n     * @param   asset  The address of the asset\n     * @param   pool  The address of the uniswap v3 pool\n     */\n    function setV3Pool(address asset, IUniswapV3Pool pool) external onlyOwner {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        address pairToken = pool.token0();\n        if (asset == pairToken) {\n            pairToken = pool.token1();\n        }\n        // Must have a chainlink aggregator for the pairedToken\n        require(\n            address(l.chainlinkV3USDAggregators[pairToken]) != address(0),\n            'no pair aggregator'\n        );\n\n        l.assetToUniV3PoolConfig[asset] = RegistryStorage.V3PoolConfig(\n            pool,\n            pairToken\n        );\n    }\n\n    /**\n     * @notice  The address of the native token wrapper for the chain deployed on\n     * @dev     ETH -> WETH, MATIC - WRAPPEDMATIC\n     * @param   _wrappedNativeToken  The address of the wrapped native token\n     */\n    function setWrappedNativeToken(\n        IWETH _wrappedNativeToken\n    ) external onlyOwner {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        l.wrappedNativeToken = _wrappedNativeToken;\n    }\n\n    /**\n     * @notice  Sets an ancillary contract address in the registry\n     * @dev     Added so we can store references to other contracts, without having to change the registry\n     * @param   _contractName  The contract name, care needs to be taken not to cause collisions, bytes32 encoded\n     * @param   _contractAddress  The address of the contract\n     */\n    function setAncillaryContractAddress(\n        bytes32 _contractName,\n        address _contractAddress\n    ) external onlyOwner {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        l.ancillaryContractAddresses[_contractName] = _contractAddress;\n    }\n\n    /// VIEWS\n\n    /**\n     * @notice  Returns the address of the given ancillary contract\n     * @dev     Added so we can store references to other contracts, without having to change the registry\n     * @dev     Potentially add a address(0) check here\n     * @param   _contractName  The contract name bytes32 encoded\n     * @return  address  The address of the contract\n     */\n    function ancillaryContractAddresses(\n        bytes32 _contractName\n    ) external view returns (address) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.ancillaryContractAddresses[_contractName];\n    }\n\n    /**\n     * @notice  Returns the address of the given ancillary contract\n     * @dev     Added so the frontend can just use string as param instead of bytes32\n     * @param   _contractName  The contract name as a string\n     * @return  address  The address of the contract\n     */\n    function ancillaryContractAddressByString(\n        string memory _contractName\n    ) external view returns (address) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        bytes32 strBytes;\n\n        assembly {\n            strBytes := mload(add(_contractName, 32))\n        }\n        return l.ancillaryContractAddresses[strBytes];\n    }\n\n    /**\n     * @notice  Returns the wrappedNativeToken\n     * @dev     The wrappedNativeToken is the native token wrapped for the chain the registry is deployed on\n     * @return  IWETH The wrapped native token address\n     */\n    function wrappedNativeToken() external view returns (IWETH) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.wrappedNativeToken;\n    }\n\n    /**\n     * @notice  Returns the uniswap v3PoolConfig for the given asset\n     * @param   asset  The address of the asset\n     * @return  RegistryStorage.V3PoolConfig  The uniswap v3 pool config(pool, pairToken)\n     */\n    function v3PoolConfig(\n        address asset\n    ) external view returns (RegistryStorage.V3PoolConfig memory) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.assetToUniV3PoolConfig[asset];\n    }\n\n    /**\n     * @notice  Returns all snxPerpsV2Erc20Wrapper addresses\n     * @dev     The snxPerpsV2Erc20Wrapper is deployed for each snx perp position in a vault\n     * @dev     This allows us to get all wrappers for offchain use/tracking\n     * @return  address[]  The list of snxPerpsV2Erc20Wrapper addresses\n     */\n    function snxPerpsV2Erc20WrapperList()\n        external\n        view\n        returns (address[] memory)\n    {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.snxPerpsV2Erc20WrapperList;\n    }\n\n    /**\n     * @notice  Returns the custom value cap for the given vault\n     * @dev     Once a vault exceeds this value, it will not accept any more deposits\n     * @param   vault  The address of the vault\n     * @return  uint256  The custom value cap in USD (Constants.VAULT_PRECISION decimals)\n     */\n    function customVaultValueCap(\n        address vault\n    ) external view returns (uint256) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.customVaultValueCaps[vault];\n    }\n\n    /**\n     * @notice  Returns the protocol fee in bips\n     * @dev     The protocols share of manager fees\n     * @return  uint256  The protocol fee in bips\n     */\n    function protocolFeeBips() external view returns (uint256) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.protocolFeeBips;\n    }\n\n    /**\n     * @notice  Returns the deposit automator\n     * @dev     DEPRECATED: Use Relay\n     * @return  address  The address of the deposit automator\n     */\n    function depositAutomator() external view returns (address) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.depositAutomator;\n    }\n\n    /**\n     * @notice  Returns the withdraw automator\n     * @dev     DEPRECATED: Use Relay\n     * @return  address  The address of the withdraw automator\n     */\n    function withdrawAutomator() external view returns (address) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.withdrawAutomator;\n    }\n\n    /**\n     * @notice  Returns the default vault value cap\n     * @dev     Once a vault exceeds this value, it will not accept any more deposits unless it has a custom cap\n     * @return  uint256  .\n     */\n    function vaultValueCap() external view returns (uint256) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.vaultValueCap;\n    }\n\n    /**\n     * @notice  Returns the max price impact that can be incurred in 24s for the given risk profile\n     * @param   riskProfile  The risk profile to get the max cpit bips for\n     * @return  uint256  The maximum amount of cpit in bips\n     */\n    function maxCpitBips(\n        VaultRiskProfile riskProfile\n    ) external view returns (uint256) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.maxCpitBips[riskProfile];\n    }\n\n    /**\n     * @notice  Returns the ParentVaultDiamond, the implementation for all Deployed Parent Vaults\n     * @dev     The ParentVaultDiamond is a diamond, so should never change\n     * @dev     Changing this will not update existing vaults\n     * @return  address  The address of the ParentVaultDiamond\n     */\n    function parentVaultDiamond() external view returns (address) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.parentVaultDiamond;\n    }\n\n    /**\n     * @notice  Returns the ChildVaultDiamond, the implementation for all Deployed Child Vaults\n     * @dev     The ChildVaultDiamond is a diamond, so should never change\n     * @dev     Changing this will not update existing vaults\n     * @return  address The address of the ChildVaultDiamond\n     */\n    function childVaultDiamond() external view returns (address) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.childVaultDiamond;\n    }\n\n    /**\n     * @notice  Returns LayerZero chainId\n     * @return  uint16  The LayerZero chainId\n     */\n    function chainId() external view returns (uint16) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.chainId;\n    }\n\n    /**\n     * @notice  Returns the protocol treasury address\n     * @return  address  The address of the protocol treasury\n     */\n    function protocolTreasury() external view returns (address) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.protocolTreasury;\n    }\n\n    /**\n     * @notice  Returns true if the given address is registed valio vault\n     * @dev     A valio vault is a vault that has been created by the valio protocol\n     * @param   vault  The address of the vault\n     * @return  bool  True if the vault is a valio vault\n     */\n    function isVault(address vault) external view returns (bool) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.parentVaults[vault] || l.childVaults[vault];\n    }\n\n    /**\n     * @notice  Returns true if the given address is registed valio parent vault\n     * @dev     A valio vault is a vault that has been created by the valio protocol\n     * @param   vault  The address of the vault\n     * @return  bool  True if the vault is a valio parent vault\n     */\n    function isVaultParent(address vault) external view returns (bool) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.parentVaults[vault];\n    }\n\n    /**\n     * @notice  Returns true if the given address is registed valio child vault\n     * @dev     A valio vault is a vault that has been created by the valio protocol\n     * @param   vault  The address of the vault\n     * @return  bool  True if the vault is a valio child vault\n     */\n    function isVaultChild(address vault) external view returns (bool) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.childVaults[vault];\n    }\n\n    /**\n     * @notice  Returns the exectutor address for the given integration\n     * @dev     The executor is responsible for checking/executing manager transactions\n     * @param   integration  The integration to get the executor for\n     * @return  address  The address of the executor contract\n     */\n    function executors(\n        ExecutorIntegration integration\n    ) external view returns (address) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.executors[integration];\n    }\n\n    /**\n     * @notice  Returns the redeemer for the given asset\n     * @dev     The redeemer is responsible for redeeming the asset from the vault\n     * @param   asset  The address of the asset\n     * @return  address  The address of the redeemer contract\n     */\n    function redeemers(address asset) external view returns (address) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.redeemers[l.assetTypes[asset]];\n    }\n\n    /**\n     * @notice  Returns the redeemer for the given asset type\n     * @dev     The redeemer is responsible for redeeming the asset from the vault\n     * @param   _assetType  The type of the asset\n     * @return  address  The address of the redeemer contract\n     */\n    function redeemerByType(\n        RegistryStorage.AssetType _assetType\n    ) external view returns (address) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.redeemers[_assetType];\n    }\n\n    /**\n     * @notice  Returns the valuer for the given asset\n     * @dev     The valuer is responsible for getting the value of the asset\n     * @param   asset  The address of the asset\n     * @return  address  The address of the valuer contract\n     */\n    function valuers(address asset) external view returns (address) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.valuers[l.assetTypes[asset]];\n    }\n\n    /**\n     * @notice  Returns the valuer for the given asset type\n     * @dev     The valuer is responsible for getting the value of the asset\n     * @param   _assetType  The type of the asset\n     * @return  address  The address of the valuer contract\n     */\n    function valuerByType(\n        RegistryStorage.AssetType _assetType\n    ) external view returns (address) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.valuers[_assetType];\n    }\n\n    /**\n     * @notice  Returns the deprecation status of the given asset\n     * @dev     Deprecated assets are not allowed to be traded into\n     * @param   asset  The address of the asset to deprecate\n     */\n    function deprecatedAssets(address asset) external view returns (bool) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.deprecatedAssets[asset];\n    }\n\n    /**\n     * @notice  Returns the hard deprecation status of the given asset\n     * @dev     Hard deprecated assets cannot be valued, vaults holding them cannot be deposited into\n     * @param   asset  The address of the asset to deprecate\n     * @return  bool  True if the asset is deprecated\n     */\n    function hardDeprecatedAssets(address asset) external view returns (bool) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.hardDeprecatedAssets[asset];\n    }\n\n    /**\n     * @notice  Returns if the given asset can be deposited into the vault\n     * @dev     Currently only USDC/USDC.e, should only be hard stables\n     * @param   asset  The address of the asset\n     * @return  bool  True if the asset can be deposited\n     */\n    function depositAssets(address asset) external view returns (bool) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.depositAssets[asset];\n    }\n\n    /**\n     * @notice  Returns the chainlink aggregator for the given asset\n     * @dev     The aggregator is responsible for getting the price of the asset\n     * @param   asset  The address of the asset\n     * @return  IAggregatorV3Interface  The address of the chainlink aggregator\n     */\n    function chainlinkV3USDAggregators(\n        address asset\n    ) external view returns (IAggregatorV3Interface) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.chainlinkV3USDAggregators[asset];\n    }\n\n    /**\n     * @notice  Returns the valioCustomAggregator for the given AggregatorType\n     * @dev     A valioCustomAggregator is responsible for getting the price of the asset\n     * @param   aggregatorType  The type of the aggregator\n     * @return  IValioCustomAggregator  The address of the valioCustomAggregator\n     */\n    function valioCustomUSDAggregators(\n        RegistryStorage.AggregatorType aggregatorType\n    ) external view returns (IValioCustomAggregator) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.valioCustomUSDAggregators[aggregatorType];\n    }\n\n    /**\n     * @notice  The max active assets a vault can have\n     * @return  uint256  The maximum number of active assets\n     */\n    function maxActiveAssets() external view returns (uint256) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.maxActiveAssets;\n    }\n\n    /**\n     * @notice  The chainlink timeout\n     * @dev     If the chainlink price is older than this, it is considered stale, valuing will revert\n     * @return  uint256  The chainlink timeout in seconds\n     */\n    function chainlinkTimeout() external view returns (uint256) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.chainlinkTimeout;\n    }\n\n    /**\n     * @notice  The deposit lockup time\n     * @dev     The deposit lockup time is the time that a deposit is locked up for.\n     * @dev     This protects lps from nefarious behaviour\n     * @return  uint256  The deposit lockup time in seconds\n     */\n    function depositLockupTime() external view returns (uint256) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.depositLockupTime;\n    }\n\n    /**\n     * @notice  The minimum deposit amount\n     * @dev     This is the minimum amount that has to be first deposited into a holding\n     * @return  uint256  The minimum deposit amount in USD (Constants.VAULT_PRECISION decimals)\n     */\n    function minDepositAmount() external view returns (uint256) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.minDepositAmount;\n    }\n\n    /**\n     * @notice  The default max deposit amount per holding\n     * @dev     This is the maximum amount that can be deposited into a holding\n     * @return  uint256 The maximum deposit amount in USD (Constants.VAULT_PRECISION decimals)\n     */\n    function maxDepositAmount() external view returns (uint256) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.maxDepositAmount;\n    }\n\n    /**\n     * @notice  Returns true if a manager can change manager\n     * @return  bool  True if the manager can change the manager\n     */\n    function canChangeManager() external view returns (bool) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.canChangeManager;\n    }\n\n    /**\n     * @notice  Returns true if a manager can change manager fees\n     * @return  bool  True if the manager can change the manager fees\n     */\n    function canChangeManagerFees() external view returns (bool) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.canChangeManagerFees;\n    }\n\n    /**\n     * @notice  Sets the liveliness threshold\n     * @dev     The liveliness threshold is the time a vault value update from a child is valid for\n     * @return  uint256 the livelinessThreshold time in seconds\n     */\n    function livelinessThreshold() external view returns (uint256) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.livelinessThreshold;\n    }\n\n    /**\n     * @notice  Returns the address of the 0x Exchange Router\n     * @return  address  The address of the 0x Exchange Router\n     */\n    function zeroXExchangeRouter() external view returns (address) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.zeroXExchangeRouter;\n    }\n\n    /**\n     * @notice  Returns the list of all parentVaults\n     * @return  address[]  List of all parentVaults\n     */\n    function vaultParentList() external view returns (address[] memory) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.parentVaultList;\n    }\n\n    /**\n     * @notice  Returns the list of all childVaults\n     * @return  address[]  List of all childVaults\n     */\n    function vaultChildList() external view returns (address[] memory) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.childVaultList;\n    }\n\n    /**\n     * @notice  Returns the list of all assets\n     * @return  address[]  Returns the list of all assets\n     */\n    function assetList() external view returns (address[] memory) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.assetList;\n    }\n\n    /**\n     * @notice  Returns the configured AggregatorType for the given asset\n     * @param   asset  The address of the asset\n     * @return  RegistryStorage.AggregatorType  The type of the aggregator\n     */\n    function assetAggregatorType(\n        address asset\n    ) external view returns (RegistryStorage.AggregatorType) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.assetAggregatorType[asset];\n    }\n\n    /**\n     * @notice  Returns the asset type for the given asset\n     * @param   asset  The address of the asset\n     * @return  RegistryStorage.AssetType  The type of the asset\n     */\n    function assetType(\n        address asset\n    ) external view returns (RegistryStorage.AssetType) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.assetTypes[asset];\n    }\n\n    // Contracts\n\n    /**\n     * @notice  Returns the address of the IntegrationDataTracker contract\n     * @return  IntegrationDataTracker  The address of the IntegrationDataTracker contract\n     */\n    function integrationDataTracker()\n        external\n        view\n        returns (IntegrationDataTracker)\n    {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.integrationDataTracker;\n    }\n\n    /**\n     * @notice  Returns the address of the snxPerpsV2Erc20WrapperDiamond contract\n     * @dev     This is the implementation for a SnxPerpsV2Erc20Wrapper\n     * @return  address  The address of the snxPerpsV2Erc20WrapperDiamond\n     */\n    function snxPerpsV2Erc20WrapperDiamond() external view returns (address) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.snxPerpsV2Erc20WrapperDiamond;\n    }\n\n    /**\n     * @notice Returns the address of the valio gmxConfig contract\n     * @dev     Only deployed on chains that support GMX\n     * @return  GmxConfig  The address of the gmxConfig contract\n     */\n    function gmxConfig() external view returns (GmxConfig) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.gmxConfig;\n    }\n\n    /**\n     * @notice  Returns the address of the valio snxConfig contract\n     * @dev     Only deployed on chains that support SNX\n     * @return  SnxConfig  The address of the snxConfig contract\n     */\n    function snxConfig() external view returns (SnxConfig) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.snxConfig;\n    }\n\n    /**\n     * @notice  Returns the address of the accountant contract\n     * @return  Accountant  The address of the accountant contract\n     */\n    function accountant() external view returns (Accountant) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.accountant;\n    }\n\n    /**\n     * @notice  Returns the address of the transport contract\n     * @return  Transport  The address of the transport contract\n     */\n    function transport() external view returns (Transport) {\n        RegistryStorage.Layout storage l = RegistryStorage.layout();\n        return l.transport;\n    }\n\n    /**\n     * @notice  Returns the precision of the vault\n     * @dev     Aka Decimals\n     * @return  uint256  The precision of the vault (decimals)\n     */\n    function VAULT_PRECISION() external pure returns (uint256) {\n        return Constants.VAULT_PRECISION;\n    }\n\n    /**\n     * @notice  Emit event that informs that the another event was emitted on the target address\n     * @param   caller  The address of the caller\n     */\n    function _emitEvent(address caller) internal {\n        emit EventEmitted(caller);\n    }\n}\n"
      },
      "contracts/registry/RegistryStorage.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nimport { Accountant } from '../Accountant.sol';\nimport { Transport } from '../transport/Transport.sol';\nimport { ExecutorIntegration } from '../executors/IExecutor.sol';\nimport { VaultRiskProfile } from '../vault-base/IVaultRiskProfile.sol';\nimport { IntegrationDataTracker } from '../integration-data-tracker/IntegrationDataTracker.sol';\nimport { GmxConfig } from '../GmxConfig.sol';\nimport { SnxConfig } from '../SnxConfig.sol';\nimport { ILayerZeroEndpoint } from '@layerzerolabs/solidity-examples/contracts/interfaces/ILayerZeroEndpoint.sol';\nimport { IAggregatorV3Interface } from '../interfaces/IAggregatorV3Interface.sol';\nimport { IWETH } from '../interfaces/IWeth.sol';\nimport { IValioCustomAggregator } from '../aggregators/IValioCustomAggregator.sol';\n\nimport { IUniswapV3Pool } from '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\n\nlibrary RegistryStorage {\n    bytes32 internal constant STORAGE_SLOT =\n        keccak256('valio.storage.Registry');\n\n    // Cannot use struct with diamond storage,\n    // as adding any extra storage slots will break the following already declared members\n    // solhint-disable-next-line ordering\n    struct VaultSettings {\n        bool ___deprecated;\n        uint ____deprecated;\n        uint _____deprecated;\n        uint ______deprecated;\n    }\n\n    // solhint-disable-next-line ordering\n    enum AssetType {\n        None,\n        GMX,\n        Erc20,\n        SnxPerpsV2\n    }\n\n    // solhint-disable-next-line ordering\n    enum AggregatorType {\n        ChainlinkV3USD,\n        UniswapV3Twap,\n        VelodromeV2Twap,\n        None, // Things like gmx return a value in usd so no aggregator is needed\n        SynthetixConversion\n    }\n\n    struct V3PoolConfig {\n        IUniswapV3Pool pool;\n        address pairToken;\n    }\n\n    // solhint-disable-next-line ordering\n    struct Layout {\n        uint16 chainId;\n        address protocolTreasury;\n        address parentVaultDiamond;\n        address childVaultDiamond;\n        mapping(address => bool) parentVaults;\n        mapping(address => bool) childVaults;\n        VaultSettings _deprecated;\n        Accountant accountant;\n        Transport transport;\n        IntegrationDataTracker integrationDataTracker;\n        GmxConfig gmxConfig;\n        mapping(ExecutorIntegration => address) executors;\n        // Price get will revert if the price hasn't be updated in the below time\n        uint256 chainlinkTimeout;\n        mapping(AssetType => address) valuers;\n        mapping(AssetType => address) redeemers;\n        mapping(address => AssetType) assetTypes;\n        // All must return USD price and be 8 decimals\n        mapping(address => IAggregatorV3Interface) chainlinkV3USDAggregators;\n        mapping(address => bool) deprecatedAssets; // Assets that cannot be traded into, only out of\n        address zeroXExchangeRouter;\n        uint DEPRECATED_zeroXMaximumSingleSwapPriceImpactBips;\n        bool canChangeManager;\n        // The number of assets that can be active at once for a vault\n        // This is important so withdraw processing doesn't consume > max gas\n        uint maxActiveAssets;\n        uint depositLockupTime;\n        uint livelinessThreshold;\n        mapping(VaultRiskProfile => uint) maxCpitBips;\n        uint DEPRECATED_maxSingleActionImpactBips;\n        uint minDepositAmount;\n        bool canChangeManagerFees;\n        // Assets that can be deposited into the vault\n        mapping(address => bool) depositAssets;\n        uint vaultValueCap;\n        bool DEPRECATED_managerWhitelistEnabled;\n        mapping(address => bool) DEPRECATED_allowedManagers;\n        bool DEPRECATED_investorWhitelistEnabled;\n        mapping(address => bool) DEPRECATED_allowedInvestors;\n        address withdrawAutomator;\n        mapping(address => IValioCustomAggregator) DEPRECATED_valioCustomUSDAggregators;\n        address[] parentVaultList;\n        address[] childVaultList;\n        address[] assetList;\n        uint maxDepositAmount;\n        uint protocolFeeBips;\n        mapping(address => AggregatorType) assetAggregatorType;\n        // All must return USD price and be 8 decimals\n        mapping(AggregatorType => IValioCustomAggregator) valioCustomUSDAggregators;\n        address depositAutomator;\n        SnxConfig snxConfig;\n        address snxPerpsV2Erc20WrapperDiamond;\n        mapping(address => uint) customVaultValueCaps;\n        address[] snxPerpsV2Erc20WrapperList;\n        // hardDeprecatedAssets Assets will return a value of 0\n        // hardDeprecatedAssets Assets that cannot be traded into, only out of\n        // A vault holding hardDeprecatedAssets will not be able be deposited into\n        mapping(address => bool) hardDeprecatedAssets;\n        mapping(address => V3PoolConfig) assetToUniV3PoolConfig;\n        IWETH wrappedNativeToken; // weth, wmatic etc\n        mapping(address => bool) isWrappedNativeToken;\n        mapping(bytes32 => address) ancillaryContractAddresses;\n    }\n\n    function layout() internal pure returns (Layout storage l) {\n        bytes32 slot = STORAGE_SLOT;\n\n        assembly {\n            l.slot := slot\n        }\n    }\n}\n"
      },
      "contracts/SnxConfig.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\nimport { ISnxAddressResolver } from './interfaces/ISnxAddressResolver.sol';\n\n/**\n * @title   SnxConfig\n * @dev     Used to store addresses and configuration values for the SNX system.\n * @notice  Ref stored in the regsitry, Only deployed on chains that support snx\n */\n\ncontract SnxConfig {\n    bytes32 public immutable trackingCode;\n    ISnxAddressResolver public immutable addressResolver;\n    address public immutable perpsV2MarketData;\n    uint8 public immutable maxPerpPositions;\n\n    constructor(\n        address _addressResolver,\n        address _perpsV2MarketData,\n        bytes32 _snxTrackingCode,\n        uint8 _maxPerpPositions\n    ) {\n        addressResolver = ISnxAddressResolver(_addressResolver);\n        // https://github.com/Synthetixio/synthetix/blob/master/contracts/PerpsV2MarketData.sol\n        perpsV2MarketData = _perpsV2MarketData;\n        trackingCode = _snxTrackingCode;\n        maxPerpPositions = _maxPerpPositions;\n    }\n}\n"
      },
      "contracts/transport/ITransport.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\nimport { VaultRiskProfile } from '../vault-base/IVaultRiskProfile.sol';\n\nenum GasFunctionType {\n    standardNoReturnMessage,\n    createChildRequiresReturnMessage,\n    getVaultValueRequiresReturnMessage,\n    withdrawRequiresReturnMessage,\n    sgReceiveRequiresReturnMessage,\n    sendBridgeApprovalNoReturnMessage,\n    childCreatedNoReturnMessage\n}\n\n/**\n * @title   ITransport\n * @dev     Interface containing expected external functions of the Transport Contract\n */\n\ninterface ITransport {\n    struct SGReceivePayload {\n        address dstVault;\n        address srcVault;\n        uint16 parentChainId;\n        address parentVault;\n    }\n\n    struct SGBridgedAssetReceivedAcknoledgementRequest {\n        uint16 parentChainId;\n        address parentVault;\n        uint16 receivingChainId;\n    }\n\n    struct ChildVault {\n        uint16 chainId;\n        address vault;\n    }\n\n    struct VaultChildCreationRequest {\n        address parentVault;\n        uint16 parentChainId;\n        uint16 newChainId;\n        address manager;\n        VaultRiskProfile riskProfile;\n        ChildVault[] children;\n    }\n\n    struct ChildCreatedRequest {\n        address parentVault;\n        uint16 parentChainId;\n        ChildVault newChild;\n    }\n\n    struct AddVaultSiblingRequest {\n        ChildVault child;\n        ChildVault newSibling;\n    }\n\n    struct BridgeApprovalRequest {\n        uint16 approvedChainId;\n        address approvedVault;\n    }\n\n    struct BridgeApprovalCancellationRequest {\n        uint16 parentChainId;\n        address parentVault;\n        address requester;\n    }\n\n    struct ValueUpdateRequest {\n        uint16 parentChainId;\n        address parentVault;\n        ChildVault child;\n    }\n\n    struct ValueUpdatedRequest {\n        uint16 parentChainId;\n        address parentVault;\n        ChildVault child;\n        uint time;\n        uint minValue;\n        uint maxValue;\n        bool hasHardDepreactedAsset;\n    }\n\n    struct WithdrawRequest {\n        uint16 parentChainId;\n        address parentVault;\n        ChildVault child;\n        uint tokenId;\n        address withdrawer;\n        uint portion;\n    }\n\n    struct WithdrawComplete {\n        uint16 parentChainId;\n        address parentVault;\n    }\n\n    struct ChangeManagerRequest {\n        ChildVault child;\n        address newManager;\n    }\n\n    event VaultChildCreated(address target);\n    event VaultParentCreated(address target);\n\n    receive() external payable;\n\n    function addSibling(AddVaultSiblingRequest memory request) external;\n\n    function bridgeApproval(BridgeApprovalRequest memory request) external;\n\n    function bridgeApprovalCancellation(\n        BridgeApprovalCancellationRequest memory request\n    ) external;\n\n    function bridgeAsset(\n        uint16 dstChainId,\n        address dstVault,\n        uint16 parentChainId,\n        address parentVault,\n        address bridgeToken,\n        uint256 amount,\n        uint256 minAmountOut\n    ) external payable;\n\n    function childCreated(ChildCreatedRequest memory request) external;\n\n    function createVaultChild(\n        VaultChildCreationRequest memory request\n    ) external;\n\n    function createParentVault(\n        string memory name,\n        string memory symbol,\n        address manager,\n        uint streamingFee,\n        uint performanceFee,\n        VaultRiskProfile riskProfile\n    ) external payable returns (address deployment);\n\n    function sendChangeManagerRequest(\n        ChangeManagerRequest memory request\n    ) external payable;\n\n    function sendAddSiblingRequest(\n        AddVaultSiblingRequest memory request\n    ) external;\n\n    function sendBridgeApproval(\n        BridgeApprovalRequest memory request\n    ) external payable;\n\n    function sendBridgeApprovalCancellation(\n        BridgeApprovalCancellationRequest memory request\n    ) external payable;\n\n    function sendVaultChildCreationRequest(\n        VaultChildCreationRequest memory request\n    ) external payable;\n\n    function sendWithdrawRequest(\n        WithdrawRequest memory request\n    ) external payable;\n\n    function sendValueUpdateRequest(\n        ValueUpdateRequest memory request\n    ) external payable;\n\n    function updateVaultValue(ValueUpdatedRequest memory request) external;\n\n    function getLzFee(\n        GasFunctionType gasFunctionType,\n        uint16 dstChainId\n    ) external returns (uint256 sendFee, bytes memory adapterParams);\n\n    // onlyThis\n    function changeManager(ChangeManagerRequest memory request) external;\n\n    function withdraw(WithdrawRequest memory request) external;\n\n    function withdrawComplete(WithdrawComplete memory request) external;\n\n    function getVaultValue(ValueUpdateRequest memory request) external;\n\n    function sgBridgedAssetReceived(\n        SGBridgedAssetReceivedAcknoledgementRequest memory request\n    ) external;\n}\n"
      },
      "contracts/transport/Transport.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nimport { TransportReceive } from './TransportReceive.sol';\nimport { TransportStargate } from './TransportStargate.sol';\n\n/**\n * @title   Transport\n * @dev     The contract that proxies/routes all messages to and from vaults to the GMP protocol.\n * @dev     It looks after the serialisation and deserialisation of messages.\n * @dev     It also includes the logic for asset bridging. Currently Stargage.\n * @dev     Transport is a Diamond and is composed of:\n * @dev     TransportBase, TransportReceive, TransportSend, TransportStargate\n * @notice  Currently we use LayerZero as the message passing provider, but this can be changed.\n */\ncontract Transport is TransportReceive, TransportStargate {\n\n}\n"
      },
      "contracts/transport/TransportBase.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nimport { ITransport, GasFunctionType } from './ITransport.sol';\nimport { VaultParentProxy } from '../vault-parent/VaultParentProxy.sol';\nimport { VaultParent } from '../vault-parent/VaultParent.sol';\n\nimport { VaultRiskProfile } from '../vault-base/IVaultRiskProfile.sol';\nimport { Registry } from '../registry/Registry.sol';\nimport { TransportStorage } from './TransportStorage.sol';\n\nimport { ILayerZeroEndpoint } from '@layerzerolabs/solidity-examples/contracts/interfaces/ILayerZeroEndpoint.sol';\n\nimport { SafeOwnable } from '@solidstate/contracts/access/ownable/SafeOwnable.sol';\n\n/**\n * @title   TransportBase\n * @notice  Acts as the base for the rest of the TransportLogic\n * @dev     Includes all setters/getters for storage, shared modifiers and createVault/CreateChildVault logic\n */\nabstract contract TransportBase is SafeOwnable, ITransport {\n    modifier onlyVault() {\n        require(_registry().isVault(msg.sender), 'not vault');\n        _;\n    }\n\n    modifier whenNotPaused() {\n        require(!_registry().paused(), 'paused');\n        _;\n    }\n\n    receive() external payable {}\n\n    /**\n     * @notice  Sets the required storage variables for the contract\n     * @param   __registry  The valio registry\n     * @param   __lzEndpoint  The LayerZero endpoint\n     * @param   __stargateRouter  The stargate router\n     */\n    function initialize(\n        address __registry,\n        address __lzEndpoint,\n        address __stargateRouter\n    ) external onlyOwner {\n        TransportStorage.Layout storage l = TransportStorage.layout();\n        l.registry = Registry(__registry);\n        l.lzEndpoint = ILayerZeroEndpoint(__lzEndpoint);\n        l.stargateRouter = __stargateRouter;\n    }\n\n    /**\n     * @notice  Creates a Parent vault and returns the address\n     * @dev     This should be moved to the Registry\n     * @param   name  The name of the vault\n     * @param   symbol  The ticker symbol of the vault\n     * @param   manager  The manager of the vault\n     * @param   streamingFee  The management fee\n     * @param   performanceFee  The performanceFee\n     * @param   riskProfile  The risk profile of the vault\n     * @return  deployment  The address of the created vault\n     */\n    function createParentVault(\n        string memory name,\n        string memory symbol,\n        address manager,\n        uint streamingFee,\n        uint performanceFee,\n        VaultRiskProfile riskProfile\n    ) external payable whenNotPaused returns (address deployment) {\n        require(msg.value >= _vaultCreationFee(), 'insufficient fee');\n        (bool sent, ) = _registry().protocolTreasury().call{ value: msg.value }(\n            ''\n        );\n        require(sent, 'Failed to process create vault fee');\n        return\n            _createParentVault(\n                name,\n                symbol,\n                manager,\n                streamingFee,\n                performanceFee,\n                riskProfile\n            );\n    }\n\n    /**\n     * @notice  Sets the TrustedRemoteAddress for a given chain id\n     * @dev     This is the Transport on another Chain\n     * @dev     This is concatenated with the address of this contract\n     * @param   _remoteChainId  the destination chain id\n     * @param   _remoteAddress  the address of the remote Transport\n     */\n    function setTrustedRemoteAddress(\n        uint16 _remoteChainId,\n        bytes calldata _remoteAddress\n    ) external onlyOwner {\n        TransportStorage.Layout storage l = TransportStorage.layout();\n        l.trustedRemoteLookup[_remoteChainId] = abi.encodePacked(\n            _remoteAddress,\n            address(this)\n        );\n    }\n\n    /**\n     * @notice  Sets the Source Chain Pool Id for a given asset\n     * @dev     https://stargateprotocol.gitbook.io/stargate/developers/pool-ids\n     * @param   asset  The address of the erc20 bridgable asset\n     * @param   poolId  The source chain stargate poolId for the asset\n     */\n    function setSGAssetToSrcPoolId(\n        address asset,\n        uint poolId\n    ) external onlyOwner {\n        TransportStorage.Layout storage l = TransportStorage.layout();\n        l.stargateAssetToSrcPoolId[asset] = poolId;\n    }\n\n    /**\n     * @notice  Sets the Destination Chain Pool Id for a given asset\n     * @dev     https://stargateprotocol.gitbook.io/stargate/developers/pool-ids\n     * @param   chainId  The destination chain id\n     * @param   asset  The address of the erc20 bridgable asset (the address on the source chain)\n     * @param   poolId  The destination chain stargate poolId for the asset\n     */\n    function setSGAssetToDstPoolId(\n        uint16 chainId,\n        address asset,\n        uint poolId\n    ) external onlyOwner {\n        TransportStorage.Layout storage l = TransportStorage.layout();\n        l.stargateAssetToDstPoolId[chainId][asset] = poolId;\n    }\n\n    /**\n     * @notice  Sets the gas consumption for the given function type\n     * @dev     This is how much destination gas will be sent for a given function\n     * @param   chainId  The destination chain id\n     * @param   gasUsageType  The function type\n     * @param   gas  The amount of gas the function will use\n     */\n    function setGasUsage(\n        uint16 chainId,\n        GasFunctionType gasUsageType,\n        uint gas\n    ) external onlyOwner {\n        TransportStorage.Layout storage l = TransportStorage.layout();\n        l.gasUsage[chainId][gasUsageType] = gas;\n    }\n\n    /**\n     * @notice  Sets the return message cost for the given chain id\n     * @dev     This is how much the destination chain will be charged for a return message\n     * @dev     This amount will be included with the src chain message to pay for the reply\n     * @param   chainId  The destination chain id\n     * @param   cost  The amount in destination chain native token (currently only eth)\n     */\n    function setReturnMessageCost(\n        uint16 chainId,\n        uint cost\n    ) external onlyOwner {\n        TransportStorage.Layout storage l = TransportStorage.layout();\n        l.returnMessageCosts[chainId] = cost;\n    }\n\n    /**\n     * @notice  Sets the amount of time that has to pass before a bridge can be cancelled by anyone\n     * @dev     This stops managers from being able to block withdraws. It is a safety mechanism.\n     * @param   time  the amount of time in seconds\n     */\n    function setBridgeApprovalCancellationTime(uint time) external onlyOwner {\n        TransportStorage.Layout storage l = TransportStorage.layout();\n        l.bridgeApprovalCancellationTime = time;\n    }\n\n    /**\n     * @notice  The fee charged to create a ParentVault\n     * @param   fee  The fee in the native token\n     */\n    function setVaultCreationFee(uint fee) external onlyOwner {\n        TransportStorage.Layout storage l = TransportStorage.layout();\n        l.vaultCreationFee = fee;\n    }\n\n    /**\n     * @notice  Returns the valio registry\n     * @return  Registry  the valio registry\n     */\n    function registry() external view returns (Registry) {\n        return _registry();\n    }\n\n    /**\n     * @notice  Returns the amount of time that has to pass before a bridge can be cancelled by anyone\n     * @return  time  the amount of time in seconds\n     */\n    function bridgeApprovalCancellationTime() external view returns (uint256) {\n        return _bridgeApprovalCancellationTime();\n    }\n\n    /**\n     * @notice  Returns the LayerZero endpoint\n     * @return  ILayerZeroEndpoint  the LayerZero endpoint\n     */\n    function lzEndpoint() external view returns (ILayerZeroEndpoint) {\n        return _lzEndpoint();\n    }\n\n    /**\n     * @notice  Returns the trusted remote address for a given chain id\n     * @dev     This is the address that is allowed to send messages to this chain\n     * @dev     LayerZeros srcAddress is concatenates the from address and the to address\n     * @param   remoteChainId  The destination chain id\n     * @return  bytes  the trusted remote address (remoteAddress + address(this))\n     */\n    function trustedRemoteLookup(\n        uint16 remoteChainId\n    ) external view returns (bytes memory) {\n        return _trustedRemoteLookup(remoteChainId);\n    }\n\n    /**\n     * @notice  Returns the stargate router\n     * @return  address  the stargate router\n     */\n    function stargateRouter() external view returns (address) {\n        return _stargateRouter();\n    }\n\n    /**\n     * @notice  Returns the destination pool id for a given asset\n     * @dev     https://stargateprotocol.gitbook.io/stargate/developers/pool-ids\n     * @param   dstChainId  The destination chainId\n     * @param   srcBridgeToken  The address of the erc20 bridgable asset\n     * @return  uint  the destination pool id\n     */\n    function stargateAssetToDstPoolId(\n        uint16 dstChainId,\n        address srcBridgeToken\n    ) external view returns (uint256) {\n        return _stargateAssetToDstPoolId(dstChainId, srcBridgeToken);\n    }\n\n    /**\n     * @notice  Returns the source pool id for a given asset\n     * @dev     https://stargateprotocol.gitbook.io/stargate/developers/pool-ids\n     * @dev     This is only used for checking configuration\n     * @param   bridgeToken  The address of the erc20 bridgable asset\n     * @return  uint  the source pool id\n     */\n    function stargateAssetToSrcPoolId(\n        address bridgeToken\n    ) external view returns (uint256) {\n        return _stargateAssetToSrcPoolId(bridgeToken);\n    }\n\n    /**\n     * @notice  Returns the gas usage for a given function type\n     * @dev     Only used for checking configuration\n     * @param   chainId  The destination chain id\n     * @param   gasFunctionType  The function type\n     * @return  uint  the amount of gas the function will use\n     */\n    function getGasUsage(\n        uint16 chainId,\n        GasFunctionType gasFunctionType\n    ) external view returns (uint) {\n        return _destinationGasUsage(chainId, gasFunctionType);\n    }\n\n    /**\n     * @notice  Returns the return message cost for a given chain id\n     * @dev     Only used for checking configuration\n     * @param   chainId  The destination chain id\n     * @return  uint  the amount of gas the function will use\n     */\n    function returnMessageCost(uint16 chainId) external view returns (uint) {\n        return _returnMessageCost(chainId);\n    }\n\n    /**\n     * @notice  Returns the fee charged to create a ParentVault\n     * @dev     Only used for checking configuration\n     * @return  uint  The fee in the native token\n     */\n    function vaultCreationFee() external view returns (uint) {\n        return _vaultCreationFee();\n    }\n\n    /**\n     * @notice  Returns the fee charged to create a ParentVault\n     * @dev     Only kept for backwards compatiblity it use to be a constant\n     * @return  uint  The fee in the native token\n     */\n    function CREATE_VAULT_FEE() external view returns (uint) {\n        return _vaultCreationFee();\n    }\n\n    /**\n     * @notice  Creates a Parent vault and returns the address\n     * @dev     Registers the parent vault with the Registry\n     * @dev     This should be moved to the Registry\n     * @param   name  The name of the vault\n     * @param   symbol  The ticker symbol of the vault\n     * @param   manager  The manager of the vault\n     * @param   streamingFee  The management fee\n     * @param   performanceFee  The performanceFee\n     * @param   riskProfile  The risk profile of the vault\n     * @return  deployment  The address of the created vault\n     */\n    function _createParentVault(\n        string memory name,\n        string memory symbol,\n        address manager,\n        uint streamingFee,\n        uint performanceFee,\n        VaultRiskProfile riskProfile\n    ) internal returns (address deployment) {\n        require(\n            _registry().parentVaultDiamond() != address(0),\n            'not parent chain'\n        );\n\n        deployment = address(\n            new VaultParentProxy(_registry().parentVaultDiamond())\n        );\n\n        VaultParent(payable(deployment)).initialize(\n            name,\n            symbol,\n            manager,\n            streamingFee,\n            performanceFee,\n            riskProfile,\n            _registry()\n        );\n\n        _registry().addVaultParent(deployment);\n\n        emit VaultParentCreated(deployment);\n        _registry().emitEvent();\n    }\n\n    /**\n     * @notice  Returns the source pool id for a given asset\n     * @dev     https://stargateprotocol.gitbook.io/stargate/developers/pool-ids\n     * @dev     This is only used for checking configuration\n     * @param   bridgeToken  The address of the erc20 bridgable asset\n     * @return  uint  the source pool id\n     */\n    function _stargateAssetToSrcPoolId(\n        address bridgeToken\n    ) internal view returns (uint256) {\n        TransportStorage.Layout storage l = TransportStorage.layout();\n        return l.stargateAssetToSrcPoolId[bridgeToken];\n    }\n\n    /**\n     * @notice  Returns the destination pool id for a given asset\n     * @dev     https://stargateprotocol.gitbook.io/stargate/developers/pool-ids\n     * @param   dstChainId  The destination chainId\n     * @param   srcBridgeToken  The address of the erc20 bridgable asset\n     * @return  uint  the destination pool id\n     */\n    function _stargateAssetToDstPoolId(\n        uint16 dstChainId,\n        address srcBridgeToken\n    ) internal view returns (uint256) {\n        TransportStorage.Layout storage l = TransportStorage.layout();\n        return l.stargateAssetToDstPoolId[dstChainId][srcBridgeToken];\n    }\n\n    /**\n     * @notice  Returns the amount of time that has to pass before a bridge can be cancelled by anyone\n     * @return  time  the amount of time in seconds\n     */\n    function _bridgeApprovalCancellationTime() internal view returns (uint256) {\n        TransportStorage.Layout storage l = TransportStorage.layout();\n        return l.bridgeApprovalCancellationTime;\n    }\n\n    /**\n     * @notice  Returns the trusted remote address for a given chain id\n     * @dev     This is the address that is allowed to send messages to this chain\n     * @dev     LayerZeros srcAddress is concatenates the from address and the to address\n     * @param   remoteChainId  The destination chain id\n     * @return  bytes  the trusted remote address (remoteAddress + address(this))\n     */\n    function _trustedRemoteLookup(\n        uint16 remoteChainId\n    ) internal view returns (bytes memory) {\n        TransportStorage.Layout storage l = TransportStorage.layout();\n        return l.trustedRemoteLookup[remoteChainId];\n    }\n\n    /**\n     * @notice  Returns the LayerZero endpoint\n     * @return  ILayerZeroEndpoint  the LayerZero endpoint\n     */\n    function _lzEndpoint() internal view returns (ILayerZeroEndpoint) {\n        TransportStorage.Layout storage l = TransportStorage.layout();\n        return l.lzEndpoint;\n    }\n\n    /**\n     * @notice  Returns the stargate router\n     * @return  address  the stargate router\n     */\n    function _stargateRouter() internal view returns (address) {\n        TransportStorage.Layout storage l = TransportStorage.layout();\n        return l.stargateRouter;\n    }\n\n    /**\n     * @notice  Returns the gas consumption for the given function type\n     * @dev     This is how much destination gas will be sent for a given function\n     * @param   chainId  The destination chain id\n     * @param   gasFunctionType  The function type\n     * @return  uint  the amount of gas the function will use\n     */\n    function _destinationGasUsage(\n        uint16 chainId,\n        GasFunctionType gasFunctionType\n    ) internal view returns (uint) {\n        TransportStorage.Layout storage l = TransportStorage.layout();\n        return l.gasUsage[chainId][gasFunctionType];\n    }\n\n    /**\n     * @notice  Returns the valio registry\n     * @return  Registry  the valio registry\n     */\n    function _registry() internal view returns (Registry) {\n        TransportStorage.Layout storage l = TransportStorage.layout();\n        return l.registry;\n    }\n\n    /**\n     * @notice  Returns the return message cost for a given chain id\n     * @dev     Only used for checking configuration\n     * @param   chainId  The destination chain id\n     * @return  uint  the amount of gas the function will use\n     */\n    function _returnMessageCost(uint16 chainId) internal view returns (uint) {\n        TransportStorage.Layout storage l = TransportStorage.layout();\n        return l.returnMessageCosts[chainId];\n    }\n\n    /**\n     * @notice  Returns the fee charged to create a ParentVault\n     * @dev     Only used for checking configuration\n     * @return  uint  The fee in the native token\n     */\n    function _vaultCreationFee() internal view returns (uint) {\n        TransportStorage.Layout storage l = TransportStorage.layout();\n        return l.vaultCreationFee;\n    }\n\n    /**\n     * @notice  Returns the destination transport address for the given chainId\n     * @dev     This extracts the address from the trustedRemoteLookup\n     * @param   dstChainId  The destination chain id\n     * @return  dstAddr  The fully formed destination transport address\n     */\n    function _getTrustedRemoteDestination(\n        uint16 dstChainId\n    ) internal view returns (address dstAddr) {\n        bytes memory trustedRemote = _trustedRemoteLookup(dstChainId);\n        require(\n            trustedRemote.length != 0,\n            'LzApp: destination chain is not a trusted source'\n        );\n        assembly {\n            dstAddr := mload(add(trustedRemote, 20))\n        }\n    }\n}\n"
      },
      "contracts/transport/TransportReceive.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nimport { VaultChildProxy } from '../vault-child/VaultChildProxy.sol';\nimport { VaultChild } from '../vault-child/VaultChild.sol';\nimport { VaultParent } from '../vault-parent/VaultParent.sol';\nimport { VaultRiskProfile } from '../vault-base/IVaultRiskProfile.sol';\n\nimport { ILayerZeroReceiver } from '@layerzerolabs/solidity-examples/contracts/interfaces/ILayerZeroReceiver.sol';\n\nimport { ITransport } from './TransportBase.sol';\nimport { TransportSend } from './TransportSend.sol';\n\nimport { Call } from '../lib/Call.sol';\n\n/**\n * @title   TransportReceive\n * @notice  This contract is responsible for receiving messages from the LayerZero\n * @dev     Any messages that is required to reply, should reply from here for A->B-A communication\n */\n\nabstract contract TransportReceive is TransportSend, ILayerZeroReceiver {\n    modifier onlyThis() {\n        require(address(this) == msg.sender, 'not this');\n        _;\n    }\n\n    /**\n     * @notice  The lzReceive function is called by the LayerZero contract\n     * @dev     We don't have any use for the LzNonce because they are delivered in order\n     * @param   srcChainId  the source chain id of the message\n     * @param   srcAddress  this (remoteAddress + address(this))\n     * @param   payload  the message payload\n     */\n    function lzReceive(\n        uint16 srcChainId,\n        bytes calldata srcAddress,\n        uint64, // nonce\n        bytes calldata payload\n    ) external {\n        require(\n            msg.sender == address(_lzEndpoint()),\n            'LzApp: invalid endpoint caller'\n        );\n\n        bytes memory trustedRemote = _trustedRemoteLookup(srcChainId);\n        require(\n            srcAddress.length == trustedRemote.length &&\n                keccak256(srcAddress) == keccak256(trustedRemote),\n            'LzApp: invalid source sending contract'\n        );\n        Call._call(address(this), payload);\n    }\n\n    ///\n    /// Message received callbacks - public onlyThis\n    ///\n\n    /**\n     * @notice  Receives a bridgeApprovalCancellation request\n     * @dev     This means the child vault no longers wants to bridge\n     * @dev     Note the `onlyThis` modifier\n     * @param   request  the cancellation parameters\n     */\n    function bridgeApprovalCancellation(\n        BridgeApprovalCancellationRequest memory request\n    ) public onlyThis {\n        VaultParent(payable(request.parentVault))\n            .receiveBridgeApprovalCancellation(request.requester);\n    }\n\n    /**\n     * @notice  Receives a bridgeApproval request\n     * @dev     This means the child vault wants to bridge\n     * @dev     Note the `onlyThis` modifier\n     * @param   request  the approval parameters\n     */\n    function bridgeApproval(\n        BridgeApprovalRequest memory request\n    ) public onlyThis {\n        VaultChild(payable(request.approvedVault)).receiveBridgeApproval();\n    }\n\n    /**\n     * @notice  Receives a withdraw request\n     * @dev     On success sends the withdraw complete acknowledgement back to the parent\n     * @dev     Only child vaults receive these\n     * @dev     Note the `onlyThis` modifier\n     * @param   request  the withdraw parameters\n     */\n    function withdraw(WithdrawRequest memory request) public onlyThis {\n        VaultChild(payable(request.child.vault)).receiveWithdrawRequest(\n            request.tokenId,\n            request.withdrawer,\n            request.portion\n        );\n\n        sendWithdrawComplete(\n            ITransport.WithdrawComplete({\n                parentChainId: request.parentChainId,\n                parentVault: request.parentVault\n            })\n        );\n    }\n\n    /**\n     * @notice  Receies the withdraw complete acknoledgment\n     * @dev     This is sent by the transport after a withdraw request\n     * @dev     Only parent vaults receive this\n     * @dev     Note the `onlyThis` modifier\n     * @param   request  .\n     */\n    function withdrawComplete(WithdrawComplete memory request) public onlyThis {\n        VaultParent(payable(request.parentVault)).receiveWithdrawComplete();\n    }\n\n    /**\n     * @notice  Receives a getVaultValue request\n     * @dev     This returns/replies the childs total aum to the parent\n     * @dev     Note the `onlyThis` modifier\n     * @param   request  the getVaultValue parameters\n     */\n    function getVaultValue(ValueUpdateRequest memory request) public onlyThis {\n        uint256 gasRemaining = gasleft();\n        try\n            // This would fail if for instance chainlink feed is stale\n            // If a callback fails the message is deemed failed to deliver by LZ and is queued\n            // Retrying it will likely not result in a better outcome and will block message delivery\n            // For other vaults\n            VaultChild(payable(request.child.vault)).getVaultValue()\n        returns (uint _minValue, uint _maxValue, bool _hasHardDeprecatedAsset) {\n            _sendValueUpdatedRequest(\n                ValueUpdatedRequest({\n                    parentChainId: request.parentChainId,\n                    parentVault: request.parentVault,\n                    child: request.child,\n                    time: block.timestamp,\n                    minValue: _minValue,\n                    maxValue: _maxValue,\n                    hasHardDepreactedAsset: _hasHardDeprecatedAsset\n                })\n            );\n        } catch {\n            // github.com/vertex-protocol/vertex-contracts\n            // /blob/3258d58eb1e56ece0513b3efcc468cc09a7414c4/contracts/Endpoint.sol#L333\n            // we need to differentiate between a revert and an out of gas\n            // the expectation is that because 63/64 * gasRemaining is forwarded\n            // we should be able to differentiate based on whether\n            // gasleft() >= gasRemaining / 64. however, experimentally\n            // even more gas can be remaining, and i don't have a clear\n            // understanding as to why. as a result we just err on the\n            // conservative side and provide two conservative\n            // asserts that should cover all cases\n            // As above in practice more than 1/64th of the gas is remaining\n            // The code that executes after the try { // here } requires more than 100k gas anyway\n            if (gasleft() <= 100_000 || gasleft() <= gasRemaining / 16) {\n                // If we revert the message will fail to deliver and need to be retried\n                // In the case of out of gas we want this message to be retried by our keeper\n                revert('getVaultValue out of gas');\n            }\n        }\n    }\n\n    /**\n     * @notice  Receives a valueUpdated request\n     * @dev     This means the child vault has send its updated value\n     * @dev     Note the `onlyThis` modifier\n     * @param   request  the valueUpdated parameters\n     */\n    function updateVaultValue(\n        ValueUpdatedRequest memory request\n    ) public onlyThis {\n        VaultParent(payable(request.parentVault)).receiveChildValue(\n            request.child.chainId,\n            request.minValue,\n            request.maxValue,\n            request.time,\n            request.hasHardDepreactedAsset\n        );\n    }\n\n    /**\n     * @notice  Receives a createVaultChild request\n     * @dev     This means the parent vault wants to create a new child\n     * @dev     Replies to the parent vault with the child address\n     * @dev     Note the `onlyThis` modifier\n     * @param   request  the createVaultChild parameters\n     */\n    function createVaultChild(\n        VaultChildCreationRequest memory request\n    ) public onlyThis {\n        address child = _deployChild(\n            request.parentChainId,\n            request.parentVault,\n            request.manager,\n            request.riskProfile,\n            request.children\n        );\n        _sendChildCreatedRequest(\n            ChildCreatedRequest({\n                parentVault: request.parentVault,\n                parentChainId: request.parentChainId,\n                newChild: ChildVault({\n                    chainId: _registry().chainId(),\n                    vault: child\n                })\n            })\n        );\n    }\n\n    /**\n     * @notice  Receives a childCreated request\n     * @dev     This means the child vault has been created\n     * @dev     Note the `onlyThis` modifier\n     * @param   request  the childCreated parameters\n     */\n    function childCreated(ChildCreatedRequest memory request) public onlyThis {\n        VaultParent(payable(request.parentVault)).receiveChildCreated(\n            request.newChild.chainId,\n            request.newChild.vault\n        );\n    }\n\n    /**\n     * @notice  Receives a addSibling request\n     * @dev     This means that the parent is syndicating a new sibling to existing children\n     * @dev     Note the `onlyThis` modifier\n     * @param   request  the addSibling parameters\n     */\n    function addSibling(AddVaultSiblingRequest memory request) public onlyThis {\n        VaultChild(payable(request.child.vault)).receiveAddSibling(\n            request.newSibling.chainId,\n            request.newSibling.vault\n        );\n    }\n\n    /**\n     * @notice  Receives a changeManager request\n     * @dev     This means the child vault wants to change its manager\n     * @param   request  the change manager parameters\n     */\n    function changeManager(\n        ChangeManagerRequest memory request\n    ) public onlyThis {\n        VaultChild(payable(request.child.vault)).receiveManagerChange(\n            request.newManager\n        );\n    }\n\n    /**\n     * @notice  Receives bridged asset acknoledgment\n     * @dev     This means the child vault has received the bridge\n     * @dev     Note the parent receives this even if its a Child->Child Bridge\n     * @dev     Which means the bridge lock can be removed\n     * @dev     Note the `onlyThis` modifier\n     * @param   request  the change risk profile parameters\n     */\n    function sgBridgedAssetReceived(\n        SGBridgedAssetReceivedAcknoledgementRequest memory request\n    ) public onlyThis {\n        VaultParent(payable(request.parentVault))\n            .receiveBridgedAssetAcknowledgement(request.receivingChainId);\n    }\n\n    /// Deploy Child\n\n    function _deployChild(\n        uint16 parentChainId,\n        address parentVault,\n        address manager,\n        VaultRiskProfile riskProfile,\n        ITransport.ChildVault[] memory children\n    ) internal whenNotPaused returns (address deployment) {\n        deployment = address(\n            new VaultChildProxy(_registry().childVaultDiamond())\n        );\n        VaultChild(payable(deployment)).initialize(\n            parentChainId,\n            parentVault,\n            manager,\n            riskProfile,\n            _registry(),\n            children\n        );\n        _registry().addVaultChild(deployment);\n\n        emit VaultChildCreated(deployment);\n        _registry().emitEvent();\n    }\n\n    function getVaultChildProxyBytecode() public pure returns (bytes memory) {\n        bytes memory bytecode = type(VaultChildProxy).creationCode;\n        return bytecode;\n    }\n}\n"
      },
      "contracts/transport/TransportSend.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nimport { GasFunctionType } from './ITransport.sol';\nimport { VaultRiskProfile } from '../vault-base/IVaultRiskProfile.sol';\nimport { TransportBase } from './TransportBase.sol';\nimport { ITransport } from './ITransport.sol';\n\n/**\n * @title   TransportSend\n * @notice  Contains the logic that serializes and sends messages to the LayerZeroEndpoint\n * @dev     This contract is intended to be inherited by the Transport contract\n */\n\nabstract contract TransportSend is TransportBase {\n    /**\n     * @notice  Only allows the message sender to be called by a VaultParent\n     */\n    modifier onlyVaultParent() {\n        require(_registry().isVaultParent(msg.sender), 'not parent vault');\n        _;\n    }\n\n    /**\n     * @notice  Only allows the message sender to be called by a VaultChild\n     */\n    modifier onlyVaultChild() {\n        require(_registry().isVaultChild(msg.sender), 'not child vault');\n        _;\n    }\n\n    /**\n     * @notice  Returns the lz fee for the give function\n     * @dev     This exposes the cost of sending particular types of messags to the vault\n     * @param   gasFunctionType  The type of message being sent\n     * @param   dstChainId  The destination lz chain id\n     * @return  sendFee  The lz fee for the message + destination gas\n     * @return  adapterParams  The lz send parameters (dest gas, native amount)\n     */\n    function getLzFee(\n        GasFunctionType gasFunctionType,\n        uint16 dstChainId\n    ) external view returns (uint256 sendFee, bytes memory adapterParams) {\n        return _getLzFee(gasFunctionType, dstChainId);\n    }\n\n    ///\n    /// Message senders\n    ///\n    /**\n     * @notice  Sends a change manager request to the destination vault\n     * @dev     This function is only callable by a VaultParent\n     * @param   request  The change manager request\n     */\n    // solhint-disable-next-line ordering\n    function sendChangeManagerRequest(\n        ChangeManagerRequest memory request\n    ) external payable whenNotPaused onlyVaultParent {\n        _send(\n            request.child.chainId,\n            abi.encodeCall(ITransport.changeManager, (request)),\n            msg.value,\n            _getAdapterParams(\n                request.child.chainId,\n                GasFunctionType.standardNoReturnMessage\n            )\n        );\n    }\n\n    /**\n     * @notice  Sends a withdraw request to the destination vault\n     * @dev     This function is only callable by a VaultParent\n     * @dev     Once the withdraw is processed the childVault will send a withdrawComplete message\n     * @param   request  The withdraw request\n     */\n    function sendWithdrawRequest(\n        WithdrawRequest memory request\n    ) external payable whenNotPaused onlyVaultParent {\n        _send(\n            request.child.chainId,\n            abi.encodeCall(ITransport.withdraw, (request)),\n            msg.value,\n            _getAdapterParams(\n                request.child.chainId,\n                GasFunctionType.withdrawRequiresReturnMessage\n            )\n        );\n    }\n\n    /**\n     * @notice  Sends a bridge approval request to a child vault\n     * @dev     This function is only callable by a VaultParent\n     * @dev     The VaultParent must know the VaultChild is going to bridge, as assets will be inflight\n     * @dev     We block deposits(syncs) and withdraws while assets are in flight\n     * @param   request  The bridge approval request\n     */\n    function sendBridgeApproval(\n        BridgeApprovalRequest memory request\n    ) external payable whenNotPaused onlyVaultParent {\n        _send(\n            request.approvedChainId,\n            abi.encodeCall(ITransport.bridgeApproval, (request)),\n            msg.value,\n            _getAdapterParams(\n                request.approvedChainId,\n                GasFunctionType.sendBridgeApprovalNoReturnMessage\n            )\n        );\n    }\n\n    /**\n     * @notice  Sends a bridge approval cancellation request to the parent\n     * @dev     This function is only callable by a VaultChild\n     * @param   request  The bridge approval cancellation request\n     */\n    function sendBridgeApprovalCancellation(\n        BridgeApprovalCancellationRequest memory request\n    ) external payable whenNotPaused onlyVaultChild {\n        _send(\n            request.parentChainId,\n            abi.encodeCall(ITransport.bridgeApprovalCancellation, (request)),\n            msg.value,\n            _getAdapterParams(\n                request.parentChainId,\n                GasFunctionType.standardNoReturnMessage\n            )\n        );\n    }\n\n    /**\n     * @notice  Sends a value update request to the destination vault\n     * @dev     When the childVault receives this it will send a valueUpdated message\n     * @dev     This function is only callable by a VaultParent\n     * @param   request  The value update request\n     */\n    function sendValueUpdateRequest(\n        ValueUpdateRequest memory request\n    ) external payable whenNotPaused onlyVaultParent {\n        _send(\n            request.child.chainId,\n            abi.encodeCall(ITransport.getVaultValue, (request)),\n            msg.value,\n            _getAdapterParams(\n                request.child.chainId,\n                GasFunctionType.getVaultValueRequiresReturnMessage\n            )\n        );\n    }\n\n    /**\n     * @notice  Sends a create child vault request to the destination chain transport\n     * @dev     The transport will construct the child vault and send back the childCreated message\n     * @param   request  The create child vault request\n     */\n    function sendVaultChildCreationRequest(\n        VaultChildCreationRequest memory request\n    ) external payable whenNotPaused onlyVaultParent {\n        require(\n            _getTrustedRemoteDestination(request.newChainId) != address(0),\n            'unsupported destination chain'\n        );\n        _send(\n            request.newChainId,\n            abi.encodeCall(ITransport.createVaultChild, (request)),\n            msg.value,\n            _getAdapterParams(\n                request.newChainId,\n                GasFunctionType.createChildRequiresReturnMessage\n            )\n        );\n    }\n\n    /// Return/Reply message senders\n\n    /**\n     * @notice  Sends an add sibling request to a child vault\n     * @dev     This function is only callable by a VaultParent\n     * @dev     When the VaultParent is notified there is a new childVault it syndicates it to the other childVaults\n     * @param   request  The add sibling request\n     */\n    function sendAddSiblingRequest(\n        AddVaultSiblingRequest memory request\n    ) external whenNotPaused onlyVaultParent {\n        (uint fee, bytes memory adapterParams) = _getLzFee(\n            GasFunctionType.standardNoReturnMessage,\n            request.child.chainId\n        );\n        _send(\n            request.child.chainId,\n            abi.encodeCall(ITransport.addSibling, (request)),\n            fee,\n            adapterParams\n        );\n    }\n\n    /**\n     * @notice  Sends a withdraw complete message to the parent vault\n     * @dev     Should only be called by the tranport when a withdrawRequest is completed\n     * @param   request  The withdraw complete message\n     */\n    function sendWithdrawComplete(WithdrawComplete memory request) internal {\n        (uint fee, bytes memory adapterParams) = _getLzFee(\n            GasFunctionType.standardNoReturnMessage,\n            request.parentChainId\n        );\n        _send(\n            request.parentChainId,\n            abi.encodeCall(ITransport.withdrawComplete, (request)),\n            fee,\n            adapterParams\n        );\n    }\n\n    /**\n     * @notice  Sends a ValueUpdatedRequest to the parent vault\n     * @dev     This function should be called by the transport when it receives a ValueUpdateRequest from the parent\n     * @dev     This has bad naming.\n     * @param   request  The value updated request\n     */\n    function _sendValueUpdatedRequest(\n        ValueUpdatedRequest memory request\n    ) internal {\n        (uint fee, bytes memory adapterParams) = _getLzFee(\n            GasFunctionType.standardNoReturnMessage,\n            request.parentChainId\n        );\n        _send(\n            request.parentChainId,\n            abi.encodeCall(ITransport.updateVaultValue, (request)),\n            fee,\n            adapterParams\n        );\n    }\n\n    /**\n     * @notice  Sends a bridgeAssetAcknowledgment to the parent vault\n     * @dev     This means the child vault has received the asset and the bridge lock can be reliquished\n     * @param   request  The bridge asset acknowledgment\n     */\n    function _sendSGBridgedAssetAcknowledment(\n        SGBridgedAssetReceivedAcknoledgementRequest memory request\n    ) internal {\n        (uint fee, bytes memory adapterParams) = _getLzFee(\n            GasFunctionType.standardNoReturnMessage,\n            request.parentChainId\n        );\n        _send(\n            request.parentChainId,\n            abi.encodeCall(ITransport.sgBridgedAssetReceived, (request)),\n            fee,\n            adapterParams\n        );\n    }\n\n    /**\n     * @notice  Sends a childCreatedRequest to the parent vault\n     * @dev     This function should be called by the transport when it executes a createChildRequest\n     * @dev     Notifies the parent vault that a new child vault has been created\n     * @param   request  The child created request\n     */\n    function _sendChildCreatedRequest(\n        ChildCreatedRequest memory request\n    ) internal {\n        (uint fee, bytes memory adapterParams) = _getLzFee(\n            GasFunctionType.childCreatedNoReturnMessage,\n            request.parentChainId\n        );\n        _send(\n            request.parentChainId,\n            abi.encodeCall(ITransport.childCreated, (request)),\n            fee,\n            adapterParams\n        );\n    }\n\n    /// Internal\n\n    /**\n     * @notice  Sends a message to the LayerZeroEndpoint\n     * @dev     This function is used to send messages to the LayerZeroEndpoint\n     * @param   dstChainId  The destination lz chain id\n     * @param   payload  The encoded function calldata with selector, to be called on the destination transport\n     * @param   sendFee  The cost to send the message\n     * @param   adapterParams  The lz send parameters (dest gas, native amount)\n     */\n    function _send(\n        uint16 dstChainId,\n        bytes memory payload,\n        uint sendFee,\n        bytes memory adapterParams\n    ) internal {\n        require(\n            address(this).balance >= sendFee,\n            'Transport: insufficient balance'\n        );\n        _lzEndpoint().send{ value: sendFee }(\n            dstChainId,\n            _trustedRemoteLookup(dstChainId),\n            payload,\n            payable(address(this)),\n            payable(address(this)),\n            adapterParams\n        );\n    }\n\n    /**\n     * @notice  Returns the lz fee for the give function\n     * @dev     This exposes the cost of sending particular types of messags to the vault\n     * @param   gasFunctionType  The type of message being sent\n     * @param   dstChainId  The destination lz chain id\n     * @return  sendFee  The lz fee for the message + destination gas\n     * @return  adapterParams  The lz send parameters (dest gas, native amount)\n     */\n    function _getLzFee(\n        GasFunctionType gasFunctionType,\n        uint16 dstChainId\n    ) internal view returns (uint256 sendFee, bytes memory adapterParams) {\n        // We just use the largest message for now\n        ChildVault memory childVault = ChildVault({\n            chainId: 0,\n            vault: address(0)\n        });\n        ChildVault[] memory childVaults = new ChildVault[](2);\n        childVaults[0] = childVault;\n        childVaults[1] = childVault;\n\n        VaultChildCreationRequest memory request = VaultChildCreationRequest({\n            parentVault: address(0),\n            parentChainId: 0,\n            newChainId: 0,\n            manager: address(0),\n            riskProfile: VaultRiskProfile.low,\n            children: childVaults\n        });\n\n        bytes memory payload = abi.encodeCall(\n            this.sendVaultChildCreationRequest,\n            (request)\n        );\n\n        address dstAddr = _getTrustedRemoteDestination(dstChainId);\n\n        adapterParams = _getAdapterParams(dstChainId, gasFunctionType);\n\n        (sendFee, ) = _lzEndpoint().estimateFees(\n            dstChainId,\n            dstAddr,\n            payload,\n            false,\n            adapterParams\n        );\n    }\n\n    /**\n     * @notice  Given the functionType returns if a return message is required\n     * @dev     I.E ValueUpdateRequest, WithdrawRequest require a return message\n     * @param   gasFunctionType  .\n     * @return  bool  .\n     */\n    function _requiresReturnMessage(\n        GasFunctionType gasFunctionType\n    ) internal pure returns (bool) {\n        if (\n            gasFunctionType == GasFunctionType.standardNoReturnMessage ||\n            gasFunctionType ==\n            GasFunctionType.sendBridgeApprovalNoReturnMessage ||\n            gasFunctionType == GasFunctionType.childCreatedNoReturnMessage\n        ) {\n            return false;\n        }\n        return true;\n    }\n\n    /**\n     * @notice  Returns the lz adapter params for the given function type\n     * @dev     This includes destination gas, return message cost, and gas receiver\n     * @param   dstChainId  The destination lz chain id\n     * @param   gasFunctionType  The type of message being sent\n     * @return  bytes  The lz adapter params\n     */\n    function _getAdapterParams(\n        uint16 dstChainId,\n        GasFunctionType gasFunctionType\n    ) internal view returns (bytes memory) {\n        bool requiresReturnMessage = _requiresReturnMessage(gasFunctionType);\n        return\n            abi.encodePacked(\n                uint16(2),\n                // The amount of gas the destination consumes when it receives the messaage\n                _destinationGasUsage(dstChainId, gasFunctionType),\n                // Amount to Airdrop to the remote transport\n                requiresReturnMessage ? _returnMessageCost(dstChainId) : 0,\n                // Gas Receiver\n                requiresReturnMessage\n                    ? _getTrustedRemoteDestination(dstChainId)\n                    : address(0)\n            );\n    }\n}\n"
      },
      "contracts/transport/TransportStargate.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nimport { IERC20 } from '@solidstate/contracts/interfaces/IERC20.sol';\nimport { SafeERC20 } from '@solidstate/contracts/utils/SafeERC20.sol';\nimport { VaultBaseExternal } from '../vault-base/VaultBaseExternal.sol';\n\nimport { IStargateRouter } from '@layerzerolabs/solidity-examples/contracts/interfaces/IStargateRouter.sol';\nimport { IStargateReceiver } from '@layerzerolabs/solidity-examples/contracts/interfaces/IStargateReceiver.sol';\n\nimport { TransportReceive } from './TransportReceive.sol';\nimport { GasFunctionType } from './ITransport.sol';\n\n/**\n * @title   TransportStargate\n * @notice  Contains the Transport logic for interfacing  with Stargate\n * @dev     Stargate is the current bridge provider\n * @dev     Note: funds are bridged between transports, the transports forward the funds to the vault\n */\n\nabstract contract TransportStargate is TransportReceive, IStargateReceiver {\n    using SafeERC20 for IERC20;\n\n    /**\n     * @notice  The stargate callback\n     * @dev     The stargate the destination contract must implement this function to receive the tokens and payload\n     * @dev     The receiver is a childVault we immediately send a Bridge Acknoledgement message to the parent\n     * @dev     This means the parent can remove the BridgeInProgressLock\n     */\n    function sgReceive(\n        uint16, // _srcChainId,\n        bytes memory, // _srcAddress\n        uint, // _nonce\n        address _token,\n        uint amountLD,\n        bytes memory _payload\n    ) external override {\n        require(msg.sender == _stargateRouter(), 'only stargate router');\n        SGReceivePayload memory payload = abi.decode(\n            _payload,\n            (SGReceivePayload)\n        );\n        // send transfer _token/amountLD to _toAddr\n        IERC20(_token).safeTransfer(payload.dstVault, amountLD);\n        VaultBaseExternal(payable(payload.dstVault)).receiveBridgedAsset(\n            _token\n        );\n        // Already on the parent chain - no need to send a message\n        if (_registry().chainId() == payload.parentChainId) {\n            this.sgBridgedAssetReceived(\n                SGBridgedAssetReceivedAcknoledgementRequest({\n                    parentChainId: payload.parentChainId,\n                    parentVault: payload.parentVault,\n                    receivingChainId: payload.parentChainId\n                })\n            );\n        } else {\n            _sendSGBridgedAssetAcknowledment(\n                SGBridgedAssetReceivedAcknoledgementRequest({\n                    parentChainId: payload.parentChainId,\n                    parentVault: payload.parentVault,\n                    receivingChainId: _registry().chainId()\n                })\n            );\n        }\n    }\n\n    /**\n     * @notice  Bridges an asset to a destination vault\n     * @dev     Constructs the sgReceive Payload to be sent with the bridged asset\n     * @param   dstChainId  The lz chainId of the destination\n     * @param   dstVault  The address of the destination vault\n     * @param   parentChainId  The lz chainId of the parentVault\n     * @param   parentVault  The address of the parentVault\n     * @param   bridgeToken  The address of the token to bridge\n     * @param   amount  The amount of tokens to bridge\n     * @param   minAmountOut  The minimum amount of tokens to receive\n     */\n    function bridgeAsset(\n        uint16 dstChainId,\n        address dstVault,\n        uint16 parentChainId,\n        address parentVault,\n        address bridgeToken,\n        uint amount,\n        uint minAmountOut\n    ) external payable whenNotPaused onlyVault {\n        require(amount > 0, 'error: swap() requires amount > 0');\n        address dstAddr = _getTrustedRemoteDestination(dstChainId);\n\n        uint srcPoolId = _stargateAssetToSrcPoolId(bridgeToken);\n        uint dstPoolId = _stargateAssetToDstPoolId(dstChainId, bridgeToken);\n        require(srcPoolId != 0, 'no srcPoolId');\n        require(dstPoolId != 0, 'no dstPoolId');\n\n        // encode payload data to send to destination contract, which it will handle with sgReceive()\n        bytes memory data = abi.encode(\n            SGReceivePayload({\n                dstVault: dstVault,\n                srcVault: msg.sender,\n                parentChainId: parentChainId,\n                parentVault: parentVault\n            })\n        );\n\n        IStargateRouter.lzTxObj memory lzTxObj = _getStargateTxObj(\n            dstChainId,\n            dstAddr,\n            parentChainId\n        );\n\n        IERC20(bridgeToken).safeTransferFrom(msg.sender, address(this), amount);\n        IERC20(bridgeToken).safeApprove(_stargateRouter(), amount);\n\n        // Stargate's Router.swap() function sends the tokens to the destination chain.\n        IStargateRouter(_stargateRouter()).swap{ value: msg.value }(\n            dstChainId, // the destination chain id\n            srcPoolId, // the source Stargate poolId\n            dstPoolId, // the destination Stargate poolId\n            payable(address(this)), // refund adddress. if msg.sender pays too much gas, return extra eth\n            amount, // total tokens to send to destination chain\n            minAmountOut, // min amount allowed out\n            lzTxObj, // default lzTxObj\n            abi.encodePacked(dstAddr), // destination address, the sgReceive() implementer\n            data // bytes payload\n        );\n    }\n\n    /**\n     * @notice  Returns the fee to bridge an asset to a destination vault\n     * @dev     The fee is calculated by the Stargate Router\n     * @param   dstChainId  the chainId of the destination\n     * @param   dstVault  the address of the destination vault\n     * @param   parentChainId  the chainId of the parentVault\n     * @param   parentVault  the address of the parentVault\n     * @return  fee  the fee to bridge the asset\n     */\n    function getBridgeAssetQuote(\n        uint16 dstChainId,\n        address dstVault,\n        uint16 parentChainId,\n        address parentVault\n    ) external view returns (uint fee) {\n        address dstAddr = _getTrustedRemoteDestination(dstChainId);\n\n        // Mock payload for quote\n        bytes memory data = abi.encode(\n            SGReceivePayload({\n                dstVault: dstVault,\n                srcVault: msg.sender,\n                parentChainId: parentChainId,\n                parentVault: parentVault\n            })\n        );\n\n        IStargateRouter.lzTxObj memory lzTxObj = _getStargateTxObj(\n            dstChainId,\n            dstAddr,\n            parentChainId\n        );\n\n        (fee, ) = IStargateRouter(_stargateRouter()).quoteLayerZeroFee(\n            dstChainId,\n            1, // function type: see Stargate Bridge.sol for all types\n            abi.encodePacked(dstAddr), // destination contract. it must implement sgReceive()\n            data,\n            lzTxObj\n        );\n    }\n\n    /**\n     * @notice  Returns the stargate lz transaction parameters\n     * @dev     Includes the destination gas for the sgReceive\n     * @dev     and the native token  to deliver for the return BridgeAcknowledge message\n     * @param   dstChainId  the chainId of the destination\n     * @param   dstTransportAddress  the address of the destination transport\n     * @param   parentChainId  the chainId of the parentVault (no return message req if the dstChain is parentChain)\n     * @return  lzTxObj the lz transaction params object\n     */\n    function _getStargateTxObj(\n        uint16 dstChainId,\n        address dstTransportAddress,\n        uint16 parentChainId\n    ) internal view returns (IStargateRouter.lzTxObj memory lzTxObj) {\n        uint DST_GAS = _destinationGasUsage(\n            dstChainId,\n            GasFunctionType.sgReceiveRequiresReturnMessage\n        );\n        return\n            IStargateRouter.lzTxObj({\n                ///\n                /// This needs to be enough for the sgReceive to execute successfully on the remote\n                /// We will need to accurately access how much the Transport.sgReceive function needs\n                ///\n                dstGasForCall: DST_GAS,\n                // Once the receiving vault receives the bridge the transport sends a message to the parent\n                // If the dstChain is the parentChain no return message is required\n                dstNativeAmount: dstChainId == parentChainId\n                    ? 0\n                    : _returnMessageCost(dstChainId),\n                dstNativeAddr: abi.encodePacked(dstTransportAddress)\n            });\n    }\n}\n"
      },
      "contracts/transport/TransportStorage.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nimport { Registry } from '../registry/Registry.sol';\nimport { ILayerZeroEndpoint } from '@layerzerolabs/solidity-examples/contracts/interfaces/ILayerZeroEndpoint.sol';\n\nimport { GasFunctionType } from './ITransport.sol';\n\nlibrary TransportStorage {\n    bytes32 internal constant STORAGE_SLOT =\n        keccak256('valio.storage.Transport');\n\n    // solhint-disable-next-line ordering\n    struct Layout {\n        Registry registry;\n        ILayerZeroEndpoint lzEndpoint;\n        mapping(address => bool) isVault;\n        mapping(uint16 => bytes) trustedRemoteLookup;\n        address stargateRouter;\n        mapping(address => uint) stargateAssetToSrcPoolId;\n        // (chainId => (asset => poolId))\n        mapping(uint16 => mapping(address => uint)) stargateAssetToDstPoolId;\n        uint bridgeApprovalCancellationTime;\n        mapping(GasFunctionType => uint) DEPRECATED_gasUsage;\n        mapping(uint16 => uint) returnMessageCosts;\n        // ChainId => (GasFunctionType => gasUsage)\n        // The amount of gas needed for delivery on the destination can change\n        // Based on the max number of assets that can be enabled in a vault on that chain\n        mapping(uint16 => mapping(GasFunctionType => uint)) gasUsage;\n        uint vaultCreationFee;\n    }\n\n    function layout() internal pure returns (Layout storage l) {\n        bytes32 slot = STORAGE_SLOT;\n\n        assembly {\n            l.slot := slot\n        }\n    }\n}\n"
      },
      "contracts/valuers/IValuer.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\n/**\n * @title   IValuer\n * @dev     The interface for a valio Valuer\n * @notice  The valuer is responsible for calculating the value an asset held by a vault\n */\n\ninterface IValuer {\n    struct AssetValue {\n        address asset;\n        uint256 totalMinValue;\n        uint256 totalMaxValue;\n        AssetBreakDown[] breakDown;\n    }\n\n    struct AssetBreakDown {\n        address asset;\n        uint256 balance;\n        uint256 minValue;\n        uint256 maxValue;\n    }\n\n    /**\n     * @notice  Returns the gross value and net value of the asset held by the vault\n     * @param   vault  The vault address\n     * @param   asset  The asset address\n     * @param   unitPrice  The unitPrice of the asset (some assets may not have a unit price)\n     * @return  minValue  The net value\n     * @return  maxValue  The gross value\n     */\n    function getVaultValue(\n        address vault,\n        address asset,\n        int256 unitPrice\n    ) external view returns (uint256 minValue, uint256 maxValue);\n\n    /**\n     * @notice  Returns the value of a given amount of an asset\n     * @dev     Assets that are not fungible with revert, individual units cannot be valued\n     * @param   amount  The amount of the asset\n     * @param   asset  The asset address\n     * @param   unitPrice  The unitPrice of the asset\n     * @return  minValue  The net value in USD (Constants.VAULT_PRECISION decimals)\n     * @return  maxValue  The gross value in USD (Constants.VAULT_PRECISION decimals)\n     */\n    function getAssetValue(\n        uint amount,\n        address asset,\n        int256 unitPrice\n    ) external view returns (uint256 minValue, uint256 maxValue);\n\n    /**\n     * @notice  Returns a value breakdown for a given asset\n     * @dev     This returns an array because later on we may support assets that have multiple tokens\n     * @param   vault  The vault address\n     * @param   asset  The asset address\n     * @param   unitPrice  The unitPrice of the asset\n     * @return  AssetValue  The asset value breakdown\n     */\n    function getAssetBreakdown(\n        address vault,\n        address asset,\n        int256 unitPrice\n    ) external view returns (AssetValue memory);\n\n    function getAssetActive(\n        address vault,\n        address asset\n    ) external view returns (bool);\n}\n"
      },
      "contracts/vault-base/IVaultRiskProfile.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nenum VaultRiskProfile {\n    low,\n    medium,\n    high\n}\n"
      },
      "contracts/vault-base/VaultBaseExternal.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nimport { Registry } from '../registry/Registry.sol';\nimport { IGmxPositionRouterCallbackReceiver } from '../interfaces/IGmxPositionRouterCallbackReceiver.sol';\nimport { VaultBaseInternal } from './VaultBaseInternal.sol';\nimport { ExecutorIntegration } from '../executors/IExecutor.sol';\nimport { VaultBaseStorage } from './VaultBaseStorage.sol';\nimport { VaultRiskProfile } from './IVaultRiskProfile.sol';\n\n/**\n * @title   VaultBaseExternal\n * @dev     Exposes some of the VaultBaseInternal functions externally.\n * @notice  The VaultChild inherits this directly, this is cut into the VaultParentDiamond\n */\n\ncontract VaultBaseExternal is\n    IGmxPositionRouterCallbackReceiver,\n    VaultBaseInternal\n{\n    /**\n     * @notice  If anyone sends ETH to the vault, it will be converted to WETH.\n     * @dev     The vault should never hold ETH\n     * @dev     Unless the vault is trying to unwrap WETH, transiently, in which case it is allowed\n     */\n    receive() external payable {\n        // We added the wrapping specifically for the gmx orderbook\n        // When a gmx decrease trigger order is executed and the collateral\n        // token is Weth it automatically converts it to ETH\n        // and sends it to the vault. Therefore we need to convert it back to weth.\n        // This if clause allows us to withdraw WETH to ETH to send in a call\n        // We use this for refunding gmx execution fees, which are returned in WETH\n        if (msg.sender != address(_registry().wrappedNativeToken())) {\n            _registry().wrappedNativeToken().deposit{ value: msg.value }();\n        }\n    }\n\n    /**\n     * @notice  Called by the transport when it receives an asset from another chain.\n     * @dev     The transport transfers the asset to the vault, we need to track the asset\n     * @param   asset  the bridged asset being received by the vault\n     */\n    function receiveBridgedAsset(address asset) external onlyTransport {\n        _receiveBridgedAsset(asset);\n    }\n\n    /**\n     * @notice  Allows the manager to execute a transaction on the vault with the supported integration\n     * @dev     NOTE: onlyManager\n     * @dev     Executors run as the Vault (Delegate call), this allows us to contain the logic of the executor\n     * @dev     When adding an additional executor, no changes to core code are needed.\n     * @dev     The executor can be audited in isolation\n     * @param   integration  Executor integration\n     * @param   encodedWithSelectorPayload  Encoded with the selector and payload to be called on the Executor\n     */\n    function execute(\n        ExecutorIntegration integration,\n        bytes memory encodedWithSelectorPayload\n    ) external payable nonReentrant onlyManager whenNotPaused {\n        ExecutorIntegration[] memory clean = new ExecutorIntegration[](0);\n        _execute(integration, encodedWithSelectorPayload, clean);\n    }\n\n    /**\n     * @notice  Allows the manager to execute a transaction on the vault with the supported integration\n     * @dev     NOTE: onlyManager\n     * @dev     Executors run as the Vault (Delegate call), this allows us to contain the logic of the executor\n     * @dev     When adding an additional executor, no changes to core code are needed.\n     * @dev     The executor can be audited in isolation\n     * @dev     This will also call the clean() method on the given integrationsToClean.\n     * @param   integration  Executor integration\n     * @param   integrationsToClean  Executor integrations where the clean() method should be called.\n     * @param   encodedWithSelectorPayload  Encoded with the selector and payload to be called on the Executor\n     */\n    function executeAndClean(\n        ExecutorIntegration integration,\n        bytes memory encodedWithSelectorPayload,\n        ExecutorIntegration[] memory integrationsToClean\n    ) external payable nonReentrant onlyManager whenNotPaused {\n        _execute(integration, encodedWithSelectorPayload, integrationsToClean);\n    }\n\n    /**\n     * @notice  GmxCallback for when orders are executed by gmx\n     * @dev     This is called by the GMX Position Router\n     * @dev     This proxies the call to the GMX Executor\n     * @param   positionKey  The gmx position key\n     * @param   isExecuted  Whether the order was executed\n     * @param   isIncrease  Whether the position was increased\n     */\n    function gmxPositionCallback(\n        bytes32 positionKey,\n        bool isExecuted,\n        bool isIncrease\n    ) external nonReentrant {\n        _gmxPositionCallback(positionKey, isExecuted, isIncrease);\n    }\n\n    /**\n     * @notice  Returns the vault's registry\n     * @dev     Used for tracking\n     * @return  Registry  the vault's registry\n     */\n    function registry() external view returns (Registry) {\n        return _registry();\n    }\n\n    /**\n     * @notice  Returns the manager of the vault\n     * @return  address  the managers address\n     */\n    function manager() external view returns (address) {\n        return _manager();\n    }\n\n    /**\n     * @notice  Returns the vault's ID\n     * @dev     Used for tracking\n     * @return  bytes32  the vault's ID\n     */\n    function vaultId() external view returns (bytes32) {\n        return _vaultId();\n    }\n\n    /**\n     * @notice  Uses the Accountant to get the AUM of the vault\n     * @dev     This is used to calculate the CPIT\n     * @return  minValue  The min value\n     * @return  maxValue  The max value\n     * @return  hasHardDeprecatedAsset  Whether the vault has a hard deprecated asset\n     */\n    function getVaultValue()\n        external\n        view\n        returns (uint minValue, uint maxValue, bool hasHardDeprecatedAsset)\n    {\n        return _getVaultValue();\n    }\n\n    /**\n     * @notice  Returns the CPIT incured by the manager in the last 24 hours\n     * @dev     Note: the CPIT is the price impact of the manager's trading\n     * @return  uint256  the CPIT\n     */\n    function getCurrentCpit() external view returns (uint256) {\n        return _getCurrentCpit();\n    }\n\n    /**\n     * @notice  Returns the risk profile of the vault\n     * @return  VaultRiskProfile  the risk profile\n     */\n    function riskProfile() external view returns (VaultRiskProfile) {\n        return _riskProfile();\n    }\n\n    /**\n     * @notice  Returns if the asset is being tracked by the vault\n     * @dev     This should be called `isActiveAsset` or `isTrackedAsset`\n     * @param   asset  .\n     * @return  bool  .\n     */\n    function enabledAssets(address asset) external view returns (bool) {\n        VaultBaseStorage.Layout storage l = VaultBaseStorage.layout();\n        return l.enabledAssets[asset];\n    }\n\n    /**\n     * @notice  Returns the assets that are tracked by the vault\n     * @dev     This should not be called assetsWithBalances, but should be called enabledAssets;\n     * @dev     Some assets are enabled even though their balance 0\n     * @dev     An example is that the collateralAsset for gmx is enabled for the life of the perp position\n     * @return  address[]  the asset addreses\n     */\n    function assetsWithBalances() external view returns (address[] memory) {\n        VaultBaseStorage.Layout storage l = VaultBaseStorage.layout();\n        return l.assets;\n    }\n\n    /**\n     * @notice  Returns how many locks an asset has\n     * @dev     Note: if an asset has locks it cannot be removed from the vault tracking\n     * @param   asset  the asset to check\n     * @return  uint256  the number of locks\n     */\n    function assetLocks(address asset) external view returns (uint256) {\n        VaultBaseStorage.Layout storage l = VaultBaseStorage.layout();\n        return l.assetLocks[asset];\n    }\n\n    /**\n     * @notice  Returns a list of any hard deprecated assets that are being tracked\n     * @dev     Note: if a vault has hard deprecated assets it cannot be valued\n     * @dev     The manager must trade out of the asset before any further deposits can be made\n     * @return  hdeprecatedAssets  the hard deprecated assets\n     */\n    function hardDeprecatedAssets()\n        external\n        view\n        returns (address[] memory hdeprecatedAssets)\n    {\n        VaultBaseStorage.Layout storage l = VaultBaseStorage.layout();\n        hdeprecatedAssets = new address[](l.assets.length);\n        uint count;\n        for (uint i = 0; i < l.assets.length; i++) {\n            if (l.registry.hardDeprecatedAssets(l.assets[i])) {\n                count++;\n                hdeprecatedAssets[i] = (l.assets[i]);\n            }\n        }\n\n        uint256 reduceLength = l.assets.length - count;\n        assembly {\n            mstore(\n                hdeprecatedAssets,\n                sub(mload(hdeprecatedAssets), reduceLength)\n            )\n        }\n    }\n\n    /**\n     * @notice  Adds an asset if it is not being tracked\n     * @dev     Note: onlyThis, can be called by Executors\n     * @param   asset  the asset to add\n     */\n    function addActiveAsset(address asset) public onlyThis {\n        _addAsset(asset);\n    }\n\n    /**\n     * @notice  Adds an asset if it is not being tracked, removes if it has no balance\n     * @dev     Note: onlyThis, can be called by Executors\n     * @dev     Should only be called when removing an asset from the vault,\n     * @dev     Or if the caller isn't sure if the asset needs to be tracked\n     * @dev     More performant to call addAsset\n     * @param   asset  the asset to update tracking\n     */\n    function updateActiveAsset(address asset) public onlyThis {\n        _updateActiveAsset(asset);\n    }\n\n    /**\n     * @notice  Adds an asset lock for the given asset\n     * @dev     Note: onlyThis, can be called by Executors\n     * @param   asset  the asset to add the lock for\n     */\n    function addAssetLock(address asset) public onlyThis {\n        _addAssetLock(asset);\n    }\n\n    /**\n     * @notice  Removes an asset lock for the given asset\n     * @dev     Note: onlyThis, can be called by Executors\n     * @param   asset  the asset to remove the lock for\n     */\n    function removeAssetLock(address asset) public onlyThis {\n        _removeAssetLock(asset);\n    }\n}\n"
      },
      "contracts/vault-base/VaultBaseInternal.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nimport { Registry } from '../registry/Registry.sol';\nimport { VaultRiskProfile } from '../vault-base/IVaultRiskProfile.sol';\nimport { IGmxPositionRouterCallbackReceiver } from '../interfaces/IGmxPositionRouterCallbackReceiver.sol';\nimport { ExecutorIntegration, IExecutor } from '../executors/IExecutor.sol';\nimport { IRedeemer } from '../redeemers/IRedeemer.sol';\nimport { Call } from '../lib/Call.sol';\nimport { VaultBaseStorage } from './VaultBaseStorage.sol';\nimport { CPIT } from '../cpit/CPIT.sol';\n\nimport { ReentrancyGuard } from '@solidstate/contracts/security/reentrancy_guard/ReentrancyGuard.sol';\nimport { IERC20 } from '@solidstate/contracts/interfaces/IERC20.sol';\nimport { SafeERC20 } from '@solidstate/contracts/utils/SafeERC20.sol';\n\n/**\n * @title   VaultBaseInternal\n * @notice  Internal functions for for both the VaultParent and VaultChild\n * @dev     This contains logic that both the parent and child need\n */\n\ncontract VaultBaseInternal is ReentrancyGuard, CPIT {\n    using SafeERC20 for IERC20;\n\n    event Withdraw(\n        uint tokenId,\n        address withdrawer,\n        uint portion,\n        address[] assets\n    );\n    event AssetAdded(address asset);\n    event AssetRemoved(address asset);\n    event BridgeReceived(address asset);\n    event BridgeSent(\n        uint16 dstChainId,\n        address dstVault,\n        address asset,\n        uint amount\n    );\n\n    /**\n     * @notice  Blocks the function if the vault is paused\n     */\n    modifier whenNotPaused() {\n        require(!_registry().paused(), 'paused');\n        _;\n    }\n\n    /**\n     * @notice  Only allows an external call from the transport\n     */\n    modifier onlyTransport() {\n        require(\n            address(_registry().transport()) == msg.sender,\n            'not transport'\n        );\n        _;\n    }\n\n    /**\n     * @notice  Only allows an external call from itself\n     * @dev     Used to allow Executors that are delegate called to call some specific functions\n     */\n    modifier onlyThis() {\n        require(address(this) == msg.sender, 'not this');\n        _;\n    }\n\n    /**\n     * @notice  Only allows an external call from the manager\n     */\n    modifier onlyManager() {\n        require(_manager() == msg.sender, 'not manager');\n        _;\n    }\n\n    /**\n     * @notice  Called when the vault is created\n     * @dev     Should not be called again\n     * @param   registry  Valio Registry\n     * @param   manager  Manager address of the vault\n     * @param   riskProfile  Risk profile of the vault\n     */\n    function initialize(\n        Registry registry,\n        address manager,\n        VaultRiskProfile riskProfile\n    ) internal {\n        require(manager != address(0), 'invalid _manager');\n        require(address(registry) != address(0), 'invalid _registry');\n\n        VaultBaseStorage.Layout storage l = VaultBaseStorage.layout();\n        l.registry = Registry(registry);\n        l.manager = manager;\n        l.riskProfile = riskProfile;\n    }\n\n    /**\n     * @notice  Allows the manager to execute a transaction on the vault with the supported integration\n     * @dev     Executors run as the Vault (Delegate call), this allows us to contain the logic of the executor\n     * @dev     When adding an additional executor, no changes to core code are needed.\n     * @dev     The executor can be audited in isolation\n     * @param   integration  Executor integration\n     * @param   encodedWithSelectorPayload  Encoded with the selector and payload to be called on the Executor\n     */\n    function _execute(\n        ExecutorIntegration integration,\n        bytes memory encodedWithSelectorPayload,\n        ExecutorIntegration[] memory cleanIntegrations\n    ) internal {\n        VaultBaseStorage.Layout storage l = VaultBaseStorage.layout();\n        address executor = l.registry.executors(integration);\n        require(executor != address(0), 'no executor');\n\n        // Runs any code thats required to tidy up positions for a given integration\n        // I.e Removes GMX positions that have been liquidated from storage\n        for (uint i = 0; i < cleanIntegrations.length; i++) {\n            address cleanExecutor = l.registry.executors(cleanIntegrations[i]);\n            require(cleanExecutor != address(0), 'no clean executor');\n            Call._delegate(cleanExecutor, abi.encodeCall(IExecutor.clean, ()));\n        }\n\n        // During withdraw we use to check if each asset was still active\n        // But this is gas intensive and adds costs to the withdrawer\n        _updateAllActiveAssets();\n\n        bool requiresCPIT = IExecutor(executor).requiresCPIT();\n\n        // Get value before manager execution, for CPIT\n        (uint minVaultValue, , ) = requiresCPIT\n            ? _getVaultValue()\n            : (0, 0, false);\n\n        // Make the external call\n        Call._delegate(executor, encodedWithSelectorPayload);\n\n        // Get value after for CPIT\n        if (requiresCPIT) {\n            (uint minVaultValueAfter, , ) = _getVaultValue();\n            _updatePriceImpact(\n                minVaultValue,\n                minVaultValueAfter,\n                _registry().maxCpitBips(l.riskProfile)\n            );\n        }\n    }\n\n    /**\n     * @notice  Allows a user to withdraw a portion of the vault\n     * @dev     The Redeemer runs as the Vault. This allows us to contain the logic of the redeemer\n     * @dev     When adding an additional redeemer, no changes to core code are needed.\n     * @dev     The redeemer can be audited in isolation\n     * @param   tokenId  Token ID of the vault (only used for tracking)\n     * @param   withdrawer  Address of the withdrawer (redeemer)\n     * @param   portion  Portion of the vault to withdraw\n     */\n    function _withdraw(\n        uint tokenId,\n        address withdrawer,\n        uint portion\n    ) internal {\n        VaultBaseStorage.Layout storage l = VaultBaseStorage.layout();\n\n        for (uint i = 0; i < l.assets.length; i++) {\n            address redeemer = l.registry.redeemers(l.assets[i]);\n            require(redeemer != address(0), 'no redeemer');\n            if (IRedeemer(redeemer).hasPreWithdraw()) {\n                Call._delegate(\n                    redeemer,\n                    abi.encodeCall(\n                        IRedeemer.preWithdraw,\n                        (tokenId, l.assets[i], withdrawer, portion)\n                    )\n                );\n            }\n        }\n\n        // We need to take a memory refence as we remove assets that are fully withdrawn\n        // And this means that the assets array will change length\n        // This should not be moved before preWithdraw because preWithdraw can add active assets\n        address[] memory assets = l.assets;\n\n        for (uint i = 0; i < assets.length; i++) {\n            address redeemer = l.registry.redeemers(assets[i]);\n            Call._delegate(\n                redeemer,\n                abi.encodeCall(\n                    IRedeemer.withdraw,\n                    (tokenId, assets[i], withdrawer, portion)\n                )\n            );\n        }\n\n        emit Withdraw(tokenId, withdrawer, portion, assets);\n        _registry().emitEvent();\n    }\n\n    /**\n     * @notice  Loops through all active assets and removes them if they are no longer active\n     * @dev     An asset is no longer active if it has no balance\n     */\n    function _updateAllActiveAssets() internal {\n        VaultBaseStorage.Layout storage l = VaultBaseStorage.layout();\n        for (uint i = 0; i < l.assets.length; i++) {\n            _updateActiveAsset(l.assets[i]);\n        }\n    }\n\n    /**\n     * @notice  Adds the asset to the asset tracking list if it is active, removes if not active\n     * @param   asset  Asset to check\n     */\n    function _updateActiveAsset(address asset) internal {\n        if (_isActive(asset)) {\n            _addAsset(asset);\n        } else {\n            _removeAsset(asset);\n        }\n    }\n\n    /**\n     * @notice  Receives the bridged asset\n     * @dev     Adds the asset to tracking\n     * @param   asset  Asset being received from the bridge\n     */\n    function _receiveBridgedAsset(address asset) internal {\n        // Force flag is set to true, because we must receive the bridged asset\n        _addAsset(asset, true);\n        emit BridgeReceived(asset);\n        _registry().emitEvent();\n    }\n\n    /**\n     * @notice  Allows a manager to bridge an asset\n     * @dev     We only pair briding ie USDC:USDC, this means we can determine a safe minout\n     * @param   dstChainId  Chain ID of the destination vault\n     * @param   dstVault  Address of the destination vault\n     * @param   parentChainId  Chain ID of the parent vault\n     * @param   vaultParent  Address of the parent vault\n     * @param   asset  Asset to bridge\n     * @param   amount  Amount of the asset to bridge\n     * @param   minAmountOut  Minimum amount of the asset to receive\n     * @param   lzFee  Fee to send to the bridge\n     */\n    function _bridgeAsset(\n        uint16 dstChainId,\n        address dstVault,\n        uint16 parentChainId,\n        address vaultParent,\n        address asset,\n        uint amount,\n        uint minAmountOut,\n        uint lzFee\n    ) internal {\n        // The max slippage the stargate ui shows is 1%\n        // check minAmountOut is within this threshold\n        uint internalMinAmountOut = (amount * 99) / 100;\n        require(minAmountOut >= internalMinAmountOut, 'minAmountOut too low');\n\n        IERC20(asset).safeApprove(address(_registry().transport()), amount);\n        _registry().transport().bridgeAsset{ value: lzFee }(\n            dstChainId,\n            dstVault,\n            parentChainId,\n            vaultParent,\n            asset,\n            amount,\n            minAmountOut\n        );\n        emit BridgeSent(dstChainId, dstVault, asset, amount);\n        _registry().emitEvent();\n        _updateActiveAsset(asset);\n    }\n\n    /**\n     * @notice  GmxCallback for when orders are executed by gmx\n     * @dev     This is called by the GMX Position Router\n     * @dev     This proxies the call to the GMX Executor\n     * @param   positionKey  The gmx position key\n     * @param   isExecuted  Whether the order was executed\n     * @param   isIncrease  Whether the position was increased\n     */\n    function _gmxPositionCallback(\n        bytes32 positionKey,\n        bool isExecuted,\n        bool isIncrease\n    ) internal {\n        VaultBaseStorage.Layout storage l = VaultBaseStorage.layout();\n        require(\n            msg.sender == address(l.registry.gmxConfig().positionRouter()),\n            'not gmx'\n        );\n        address executor = l.registry.executors(ExecutorIntegration.GMX);\n        require(executor != address(0), 'no executor');\n        Call._delegate(\n            executor,\n            abi.encodeCall(\n                IGmxPositionRouterCallbackReceiver.gmxPositionCallback,\n                (positionKey, isExecuted, isIncrease)\n            )\n        );\n    }\n\n    /**\n     * @notice  Adds a lock to the asset\n     * @dev     This is used to prevent the asset from being removed\n     * @dev     There can be multiple locks on an asset\n     * @dev     EG. If a GMX position is liquidated we dont receive an event\n     * @dev     And residual funds are returned to the vault in the collateral token\n     * @dev     Its the lockers responsibility to remove the lock\n     * @param   asset  Asset to lock\n     */\n    function _addAssetLock(address asset) internal {\n        VaultBaseStorage.Layout storage l = VaultBaseStorage.layout();\n        require(l.enabledAssets[asset], 'lock: asset not enabled');\n        l.assetLocks[asset] += 1;\n    }\n\n    /**\n     * @notice  Removes a lock from the asset\n     * @dev     There can be multiple locks on an asset\n     * @dev     Its the lockers responsiblity to remove the lock when appropriate\n     * @param   asset  Asset to unlock\n     */\n    function _removeAssetLock(address asset) internal {\n        VaultBaseStorage.Layout storage l = VaultBaseStorage.layout();\n        if (l.assetLocks[asset] > 0) {\n            l.assetLocks[asset] -= 1;\n        }\n    }\n\n    /**\n     * @notice  Removes an asset from tracking\n     * @dev     Will return early if asset is under lock\n     * @param   asset  .\n     */\n    function _removeAsset(address asset) internal {\n        VaultBaseStorage.Layout storage l = VaultBaseStorage.layout();\n        if (l.assetLocks[asset] > 0) {\n            return;\n        }\n        if (l.enabledAssets[asset]) {\n            for (uint i = 0; i < l.assets.length; i++) {\n                if (l.assets[i] == asset) {\n                    _removeFromArray(l.assets, i);\n                    l.enabledAssets[asset] = false;\n\n                    emit AssetRemoved(asset);\n                    _registry().emitEvent();\n                }\n            }\n        }\n    }\n\n    /**\n     * @notice  Adds an asset to tracking\n     * @dev     Will return early if asset is already tracked\n     * @param   asset  Asset to add\n     */\n    function _addAsset(address asset) internal {\n        _addAsset(asset, false);\n    }\n\n    /**\n     * @notice  Adds an asset to tracking\n     * @dev     The force flag is used when assets are bridged and we must receive them\n     * @dev     It circumvents the maxActiveAssets check\n     * @param   asset  Asset to add\n     * @param   force  Whether to force the asset to be added\n     */\n    function _addAsset(address asset, bool force) internal {\n        VaultBaseStorage.Layout storage l = VaultBaseStorage.layout();\n        require(\n            l.registry.accountant().isSupportedAsset(asset),\n            'asset not supported'\n        );\n        if (!l.enabledAssets[asset]) {\n            l.enabledAssets[asset] = true;\n            l.assets.push(asset);\n            require(\n                force || l.assets.length <= l.registry.maxActiveAssets(),\n                'too many assets'\n            );\n\n            emit AssetAdded(asset);\n            _registry().emitEvent();\n        }\n    }\n\n    /**\n     * @notice  Removes an address from an array\n     * @dev     This is used to remove assets from the assets array\n     * @param   array  the array to remove from\n     * @param   index  the index to remove\n     */\n    function _removeFromArray(address[] storage array, uint index) internal {\n        require(index < array.length);\n        array[index] = array[array.length - 1];\n        array.pop();\n    }\n\n    /**\n     * @notice  Changes the manager of the vault\n     * @dev     This is used to change the manager of the vault\n     * @param   newManager  the new manager address\n     */\n    function _changeManager(address newManager) internal {\n        VaultBaseStorage.Layout storage l = VaultBaseStorage.layout();\n        l.manager = newManager;\n    }\n\n    /**\n     * @notice  Sets the vault ID\n     * @dev     Used for offchain tracking\n     * @dev     Only call on vault initialize\n     * @param   vaultId  the vault ID\n     */\n    function _setVaultId(bytes32 vaultId) internal {\n        VaultBaseStorage.Layout storage l = VaultBaseStorage.layout();\n        l.vaultId = vaultId;\n    }\n\n    /**\n     * @notice  Returns the valio registry\n     * @return  Registry  the valio registry\n     */\n    function _registry() internal view returns (Registry) {\n        VaultBaseStorage.Layout storage l = VaultBaseStorage.layout();\n        return l.registry;\n    }\n\n    /**\n     * @notice  Returns the risk profile of the vault\n     * @return  VaultRiskProfile  the risk profile of the vault\n     */\n    function _riskProfile() internal view returns (VaultRiskProfile) {\n        VaultBaseStorage.Layout storage l = VaultBaseStorage.layout();\n        return l.riskProfile;\n    }\n\n    /**\n     * @notice  Returns the manager of the vault\n     * @return  address  the manager of the vault\n     */\n    function _manager() internal view returns (address) {\n        VaultBaseStorage.Layout storage l = VaultBaseStorage.layout();\n        return l.manager;\n    }\n\n    /**\n     * @notice  Returns the vault ID\n     * @dev     Used for offchain tracking\n     * @return  bytes32  the vault ID\n     */\n    function _vaultId() internal view returns (bytes32) {\n        VaultBaseStorage.Layout storage l = VaultBaseStorage.layout();\n        return l.vaultId;\n    }\n\n    /**\n     * @notice  Uses the Accountant to get the AUM of the vault\n     * @dev     This is used to calculate the CPIT\n     * @return  minValue  The min value\n     * @return  maxValue  The max value\n     * @return  hasHardDeprecatedAsset  Whether the vault has a hard deprecated asset\n     */\n    function _getVaultValue()\n        internal\n        view\n        returns (uint minValue, uint maxValue, bool hasHardDeprecatedAsset)\n    {\n        return _registry().accountant().getVaultValue(address(this));\n    }\n\n    /**\n     * @notice  Returns if the asset is being tracked\n     * @param   asset  Asset to check\n     * @return  bool  True if the asset is being tracked\n     */\n    function _isActive(address asset) internal view returns (bool) {\n        return _registry().accountant().assetIsActive(asset, address(this));\n    }\n}\n"
      },
      "contracts/vault-base/VaultBaseStorage.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nimport { Registry } from '../registry/Registry.sol';\n\nimport { VaultRiskProfile } from '../vault-base/IVaultRiskProfile.sol';\n\nlibrary VaultBaseStorage {\n    bytes32 internal constant STORAGE_SLOT =\n        keccak256('valio.storage.VaultBase');\n\n    // solhint-disable-next-line ordering\n    struct Layout {\n        Registry registry;\n        address manager;\n        address[] assets;\n        mapping(address => bool) enabledAssets;\n        VaultRiskProfile riskProfile;\n        bytes32 vaultId;\n        // For instance a GMX position can get liquidated at anytime and any collateral\n        // remaining is returned to the vault. But the vault is not notified.\n        // In this case the collateralToken might not be tracked by the vault anymore\n        // To resolve this: A GmxPosition will increament the assetLock for the collateralToken, meaning that it cannot\n        // be removed from enabledAssets until the lock for the asset reaches 0\n        // Any code that adds a lock is responsible for removing the lock\n        mapping(address => uint256) assetLocks;\n    }\n\n    function layout() internal pure returns (Layout storage l) {\n        bytes32 slot = STORAGE_SLOT;\n\n        assembly {\n            l.slot := slot\n        }\n    }\n}\n"
      },
      "contracts/vault-child/VaultChild.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nimport { ITransport, GasFunctionType } from '../transport/ITransport.sol';\nimport { VaultBaseInternal } from '../vault-base/VaultBaseInternal.sol';\nimport { VaultBaseExternal } from '../vault-base/VaultBaseExternal.sol';\nimport { VaultRiskProfile } from '../vault-base/IVaultRiskProfile.sol';\nimport { Registry } from '../registry/Registry.sol';\nimport { RegistryStorage } from '../registry/RegistryStorage.sol';\nimport { VaultChildStorage } from './VaultChildStorage.sol';\n\nimport { IRedeemerEvents } from '../redeemers/IRedeemerEvents.sol';\nimport { IExecutorEvents } from '../executors/IExecutorEvents.sol';\n\nimport { IStargateRouter } from '@layerzerolabs/solidity-examples/contracts/interfaces/IStargateRouter.sol';\n\n/**\n * @title   VaultChild\n * @notice  The VaultChild is a child of the VaultParent and is used to the VaultParent to hold funds on other chains\n * @dev     Contains all the logic for the VaultChild\n * @dev     The VaultChild is just a container for assets that a manager controls\n */\n\ncontract VaultChild is\n    VaultBaseInternal,\n    VaultBaseExternal,\n    IRedeemerEvents,\n    IExecutorEvents\n{\n    event BridgeApprovalReceived(uint time);\n\n    /**\n     * @notice  The VaultChild is approved to bridge to the parent or sibling\n     * @dev     This modifier is used to ensure that the VaultChild is approved to bridge\n     * @dev     The VaultParent must know the VaultChild is going to bridge, as assets will be inflight\n     * @dev     We block deposits(syncs) and withdraws while assets are in flight\n     */\n    modifier bridgingApproved() {\n        VaultChildStorage.Layout storage l = VaultChildStorage.layout();\n\n        require(l.bridgeApproved, 'bridge not approved');\n        _;\n    }\n\n    /**\n     * @notice  Initializes the VaultChild\n     * @dev     Only called once when the VaultChild is created, calls initializes of superclasses\n     * @param   _parentChainId  The lz chainId of the parent chain\n     * @param   _vaultParentAddress  The address of the parent vault\n     * @param   __manager  the manager of the vault\n     * @param   __riskProfile  the risk profile of the vault\n     * @param   __registry  the valio registry\n     * @param   _existingSiblings  the existing siblings of the vault (other child vaults on other chains)\n     */\n    function initialize(\n        uint16 _parentChainId,\n        address _vaultParentAddress,\n        address __manager,\n        VaultRiskProfile __riskProfile,\n        Registry __registry,\n        ITransport.ChildVault[] memory _existingSiblings\n    ) external {\n        require(_vaultId() == 0, 'already initialized');\n\n        VaultChildStorage.Layout storage l = VaultChildStorage.layout();\n        VaultBaseInternal.initialize(__registry, __manager, __riskProfile);\n        require(_parentChainId != 0, 'invalid _parentChainId');\n        require(\n            _vaultParentAddress != address(0),\n            'invalid _vaultParentAddress'\n        );\n\n        bytes32 __vaultId = keccak256(\n            abi.encodePacked(_parentChainId, _vaultParentAddress)\n        );\n        _setVaultId(__vaultId);\n\n        l.parentChainId = _parentChainId;\n        l.vaultParent = _vaultParentAddress;\n        for (uint8 i = 0; i < _existingSiblings.length; i++) {\n            l.siblingChains.push(_existingSiblings[i].chainId);\n            l.siblings[_existingSiblings[i].chainId] = _existingSiblings[i]\n                .vault;\n        }\n    }\n\n    ///\n    /// Receivers/CallBacks\n    ///\n\n    /**\n     * @notice  Called by the parent chain to add a new sibling to the VaultChild\n     * @dev     This allows the child to bridge to another child (sibling)\n     * @param   siblingChainId  The lz chainId of the sibling\n     * @param   siblingVault  The address of the sibling vault\n     */\n    function receiveAddSibling(\n        uint16 siblingChainId,\n        address siblingVault\n    ) external onlyTransport {\n        VaultChildStorage.Layout storage l = VaultChildStorage.layout();\n\n        l.siblings[siblingChainId] = siblingVault;\n        l.siblingChains.push(siblingChainId);\n    }\n\n    /**\n     * @notice  Called by the parent chain to approve the bridge\n     * @dev     The parent chain must approve the bridge before the child can bridge\n     * @dev     The VaultParent must know the VaultChild is going to bridge, as assets will be inflight\n     * @dev     We block deposits(syncs) and withdraws while assets are in flight\n     */\n    function receiveBridgeApproval() external onlyTransport {\n        VaultChildStorage.Layout storage l = VaultChildStorage.layout();\n\n        l.bridgeApproved = true;\n        l.bridgeApprovalTime = block.timestamp;\n        _registry().emitEvent();\n        emit BridgeApprovalReceived(block.timestamp);\n    }\n\n    /**\n     * @notice  Called by the parent chain to request a Withdraw\n     * @dev     The vault child has no concept of `shares` only `portion`\n     * @dev     The portion is calculated on the Parent chain and sent to the child\n     * @dev     Based on the number of shares burned relative to the total outstanding shares\n     * @param   tokenId  The tokenId of holding (only used for tracking)\n     * @param   withdrawer  The address of the withdrawer\n     * @param   portion  The portion of the vault to withdraw\n     */\n    function receiveWithdrawRequest(\n        uint tokenId,\n        address withdrawer,\n        uint portion\n    ) external nonReentrant onlyTransport {\n        _withdraw(tokenId, withdrawer, portion);\n    }\n\n    /**\n     * @notice  Called by the parent chain to request a manager change\n     * @param   newManager  The address of the new manager\n     */\n    function receiveManagerChange(address newManager) external onlyTransport {\n        _changeManager(newManager);\n    }\n\n    ///\n    /// Cross Chain Requests\n    ///\n\n    //\n    /**\n     * @notice  Sends a message to the Parent cancelling the bridgeApproval.\n     * @dev     The VaultParent must know the VaultChild is going to bridge, as assets will be inflight\n     * @dev     We block deposits(syncs) and withdraws while assets are in flight\n     * @dev     Allows anyone to cancel the bridge lock on the parent after 5 minutes\n     * @dev     This stops a bad manager from blocking withdraws\n     */\n    function requestBridgeApprovalCancellation()\n        external\n        payable\n        whenNotPaused\n    {\n        VaultChildStorage.Layout storage l = VaultChildStorage.layout();\n\n        require(l.bridgeApproved, 'must be already approved');\n        uint timeout = _registry().transport().bridgeApprovalCancellationTime();\n\n        if (msg.sender != _manager()) {\n            require(\n                l.bridgeApprovalTime + timeout < block.timestamp,\n                'cannot cancel yet'\n            );\n        }\n\n        l.bridgeApproved = false;\n        l.bridgeApprovalTime = 0;\n        _registry().transport().sendBridgeApprovalCancellation{\n            value: msg.value\n        }(\n            ITransport.BridgeApprovalCancellationRequest({\n                parentChainId: l.parentChainId,\n                parentVault: l.vaultParent,\n                requester: msg.sender\n            })\n        );\n    }\n\n    /**\n     * @notice  Bridges an asset to another chain\n     * @param   dstChainId  The lz chainId of the destination chain (must have parent/sibling on this chain)\n     * @param   asset  The address of the asset to bridge\n     * @param   amount  The amount of the asset to bridge\n     * @param   minAmountOut  The minimum amount of the asset to receive on the destination chain\n     */\n    function requestBridgeToChain(\n        uint16 dstChainId,\n        address asset,\n        uint amount,\n        uint minAmountOut,\n        uint // unused, kept for compatibility\n    ) external payable onlyManager whenNotPaused bridgingApproved {\n        VaultChildStorage.Layout storage l = VaultChildStorage.layout();\n\n        address dstVault;\n        if (dstChainId == l.parentChainId) {\n            dstVault = l.vaultParent;\n        } else {\n            dstVault = l.siblings[dstChainId];\n        }\n\n        require(dstVault != address(0), 'no dst vault');\n\n        l.bridgeApproved = false;\n        l.bridgeApprovalTime = 0;\n        _bridgeAsset(\n            dstChainId,\n            dstVault,\n            l.parentChainId,\n            l.vaultParent,\n            asset,\n            amount,\n            minAmountOut,\n            msg.value\n        );\n    }\n\n    ///\n    /// Views\n    ///\n\n    /**\n     * @notice  Returns the lz parentChainId\n     * @return  uint16  The lz parentChainId\n     */\n    function parentChainId() external view returns (uint16) {\n        VaultChildStorage.Layout storage l = VaultChildStorage.layout();\n\n        return l.parentChainId;\n    }\n\n    /**\n     * @notice  Returns the address of the parent vault\n     * @return  address  The address of the parent vault\n     */\n    function parentVault() external view returns (address) {\n        VaultChildStorage.Layout storage l = VaultChildStorage.layout();\n\n        return l.vaultParent;\n    }\n\n    /**\n     * @notice  Returns the lz chainids where it has a sibling\n     * @return  uint16[]  The lz chain ids where it has a sibling\n     */\n    function allSiblingChainIds() external view returns (uint16[] memory) {\n        VaultChildStorage.Layout storage l = VaultChildStorage.layout();\n        return l.siblingChains;\n    }\n\n    /**\n     * @notice  Returns the childVault address if it has a sibling on the given lz chain id\n     * @param   chainId  The lz chain id\n     * @return  address  The address of the sibling vault\n     */\n    function siblings(uint16 chainId) external view returns (address) {\n        VaultChildStorage.Layout storage l = VaultChildStorage.layout();\n        return l.siblings[chainId];\n    }\n\n    /**\n     * @notice  Returns if the child is approved to bridge\n     * @dev     Frontend helper\n     * @return  bool  True if the child is approved to bridge\n     */\n    function bridgeApproved() external view returns (bool) {\n        VaultChildStorage.Layout storage l = VaultChildStorage.layout();\n        return l.bridgeApproved;\n    }\n\n    /**\n     * @notice  When the child was approved to bridge\n     * @dev     Used to determine if the bridge can be cancelled by any user\n     * @return  uint  The time the child was approved to bridge\n     */\n    function bridgeApprovalTime() external view returns (uint) {\n        VaultChildStorage.Layout storage l = VaultChildStorage.layout();\n        return l.bridgeApprovalTime;\n    }\n\n    /**\n     * @notice  Returns the lz fee for the give function\n     * @dev     This is a helper method for the frontend\n     * @dev     We use the sighash of the intended function call to identify the action\n     * @param   sigHash  The sighash of the intended function call\n     * @param   chainId  The destination lz chain id\n     * @return  fee  The lz fee for the message + destination gas\n     */\n    function getLzFee(\n        bytes4 sigHash,\n        uint16 chainId\n    ) external view returns (uint fee) {\n        if (sigHash == this.requestBridgeToChain.selector) {\n            fee = _bridgeQuote(chainId);\n        } else {\n            (fee, ) = _registry().transport().getLzFee(\n                GasFunctionType.standardNoReturnMessage,\n                chainId\n            );\n        }\n    }\n\n    /**\n     * @notice  Returns the fee for executing a bridge\n     * @dev     Currently this is stargate, but could be different in the future\n     * @param   dstChainId  The destination lz chain id\n     * @return  fee  The stargate fee for the bridge\n     */\n    function _bridgeQuote(uint16 dstChainId) internal view returns (uint fee) {\n        VaultChildStorage.Layout storage l = VaultChildStorage.layout();\n\n        address dstVault;\n        if (dstChainId == l.parentChainId) {\n            dstVault = l.vaultParent;\n        } else {\n            dstVault = l.siblings[dstChainId];\n        }\n\n        require(dstVault != address(0), 'no dst vault');\n\n        fee = _registry().transport().getBridgeAssetQuote(\n            dstChainId,\n            dstVault,\n            l.parentChainId,\n            l.vaultParent\n        );\n    }\n}\n"
      },
      "contracts/vault-child/VaultChildProxy.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nimport { Proxy } from '@solidstate/contracts/proxy/Proxy.sol';\nimport { IDiamondReadable } from '@solidstate/contracts/proxy/diamond/readable/IDiamondReadable.sol';\n\n/**\n * @title   VaultChildProxy\n * @dev     An instance of this is created when a manager creates a ChildVault\n * @notice  This proxies to the VaultChildDiamond which is its `implementation`\n */\ncontract VaultChildProxy is Proxy {\n    address private immutable DIAMOND;\n\n    constructor(address diamond) {\n        DIAMOND = diamond;\n    }\n\n    function _getImplementation() internal view override returns (address) {\n        return IDiamondReadable(DIAMOND).facetAddress(msg.sig);\n    }\n}\n"
      },
      "contracts/vault-child/VaultChildStorage.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nlibrary VaultChildStorage {\n    bytes32 internal constant STORAGE_SLOT =\n        keccak256('valio.storage.VaultChild');\n\n    // solhint-disable-next-line ordering\n    struct Layout {\n        bytes32 _deprecated_vaultId;\n        uint16 parentChainId;\n        address vaultParent;\n        bool bridgeApproved;\n        uint bridgeApprovalTime;\n        uint16[] siblingChains;\n        mapping(uint16 => address) siblings;\n    }\n\n    function layout() internal pure returns (Layout storage l) {\n        bytes32 slot = STORAGE_SLOT;\n\n        assembly {\n            l.slot := slot\n        }\n    }\n}\n"
      },
      "contracts/vault-fees/VaultFees.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\nimport { VaultFeesStorage } from './VaultFeesStorage.sol';\nimport { Constants } from '../lib/Constants.sol';\n\n/**\n * @title   VaultFees\n * @dev     Logic for calculating and updating manager fees\n * @dev     Fees are calculated on a per holding basis\n * @dev     Performance fees are fees on profit\n * @dev     Streaming fees are fees on aum charged over time\n */\n\ncontract VaultFees {\n    uint internal constant _STEAMING_FEE_DURATION = 365 days;\n\n    uint internal constant _MAX_STREAMING_FEE_BASIS_POINTS = 500; // 5%\n    uint internal constant _MAX_STREAMING_FEE_BASIS_POINTS_STEP = 50; // 0.5%\n    uint internal constant _MAX_PERFORMANCE_FEE_BASIS_POINTS = 5_000; // 50%\n    uint internal constant _MAX_PERFORMANCE_FEE_BASIS_POINTS_STEP = 1_000; // 10%\n    uint internal constant _FEE_ANNOUNCE_WINDOW = 30 days;\n\n    event FeeIncreaseAnnounced(uint streamingFee, uint performanceFee);\n    event FeeIncreaseCommitted(uint streamingFee, uint performanceFee);\n    event FeeIncreaseRenounced();\n    event ReferrerShareUpdated(uint256 referrerShareBips);\n\n    /**\n     * @notice  Initialize the vault fees\n     * @dev     Can only be called once on deployment\n     * @param   _managerStreamingFeeBasisPoints  the initial manager streaming fee\n     * @param   _managerPerformanceFeeBasisPoints  the initial manager performance fee\n     */\n    function initialize(\n        uint _managerStreamingFeeBasisPoints,\n        uint _managerPerformanceFeeBasisPoints\n    ) internal {\n        VaultFeesStorage.Layout storage l = VaultFeesStorage.layout();\n        require(\n            _managerStreamingFeeBasisPoints <= _MAX_STREAMING_FEE_BASIS_POINTS,\n            'streamingFee to high'\n        );\n        require(\n            _managerPerformanceFeeBasisPoints <=\n                _MAX_PERFORMANCE_FEE_BASIS_POINTS,\n            'performanceFee to high'\n        );\n        l.managerStreamingFee = _managerStreamingFeeBasisPoints;\n        l.managerPerformanceFee = _managerPerformanceFeeBasisPoints;\n    }\n\n    /**\n     * @notice  Set the referrer share\n     * @dev     The referrer share is taken from the managers net fees and given to the referrer\n     * @param   referrerShareBips  the referrer share in basis points (ie 10% of manager fees)\n     */\n    function _setReferrerShareBips(uint256 referrerShareBips) internal {\n        require(\n            referrerShareBips <= Constants.BASIS_POINTS_DIVISOR,\n            'referrerShare to high'\n        );\n        VaultFeesStorage.Layout storage l = VaultFeesStorage.layout();\n        l.referrerShareBips = referrerShareBips;\n        emit ReferrerShareUpdated(referrerShareBips);\n    }\n\n    /**\n     * @notice  Announce a fee increase\n     * @dev     The fee increase will be active after a delay\n     * @dev     This protect investors from sudden fee increases\n     * @dev     They must wait the _FEE_ANNOUNCE_WINDOW before commiting the change\n     * @param   newStreamingFee  The streaming fee in basis points\n     * @param   newPerformanceFee  The performance fee in basis points\n     */\n    function _announceFeeIncrease(\n        uint256 newStreamingFee,\n        uint256 newPerformanceFee\n    ) internal {\n        require(\n            newStreamingFee <= _MAX_STREAMING_FEE_BASIS_POINTS,\n            'streamingFee to high'\n        );\n\n        VaultFeesStorage.Layout storage l = VaultFeesStorage.layout();\n\n        require(\n            newStreamingFee <=\n                l.managerStreamingFee + _MAX_STREAMING_FEE_BASIS_POINTS_STEP,\n            'streamingFee step exceeded'\n        );\n        require(\n            newPerformanceFee <= _MAX_PERFORMANCE_FEE_BASIS_POINTS,\n            'performanceFee to high'\n        );\n        require(\n            newPerformanceFee <=\n                l.managerPerformanceFee +\n                    _MAX_PERFORMANCE_FEE_BASIS_POINTS_STEP,\n            'performanceFee step exceeded'\n        );\n\n        l.announcedFeeIncreaseTimestamp = block.timestamp;\n        l.announcedManagerStreamingFee = newStreamingFee;\n        l.announcedManagerPerformanceFee = newPerformanceFee;\n        emit FeeIncreaseAnnounced(newStreamingFee, newPerformanceFee);\n    }\n\n    /**\n     * @notice  Allows the manager to renounce a fee increase\n     * @dev     Can be called at anytime\n     */\n    function _renounceFeeIncrease() internal {\n        VaultFeesStorage.Layout storage l = VaultFeesStorage.layout();\n\n        require(\n            l.announcedFeeIncreaseTimestamp != 0,\n            'no fee increase announced'\n        );\n\n        l.announcedFeeIncreaseTimestamp = 0;\n        l.announcedManagerStreamingFee = 0;\n        l.announcedManagerPerformanceFee = 0;\n\n        emit FeeIncreaseRenounced();\n    }\n\n    /**\n     * @notice  Commits the fee increase previously announced\n     * @dev     Can only be called after _FEE_ANNOUNCE_WINDOW has passed\n     */\n    function _commitFeeIncrease() internal {\n        VaultFeesStorage.Layout storage l = VaultFeesStorage.layout();\n\n        require(\n            l.announcedFeeIncreaseTimestamp != 0,\n            'no fee increase announced'\n        );\n        require(\n            block.timestamp >=\n                l.announcedFeeIncreaseTimestamp + _FEE_ANNOUNCE_WINDOW,\n            'fee delay active'\n        );\n\n        l.managerStreamingFee = l.announcedManagerStreamingFee;\n        l.managerPerformanceFee = l.announcedManagerPerformanceFee;\n\n        l.announcedFeeIncreaseTimestamp = 0;\n        l.announcedManagerStreamingFee = 0;\n        l.announcedManagerPerformanceFee = 0;\n\n        emit FeeIncreaseCommitted(\n            l.managerStreamingFee,\n            l.managerPerformanceFee\n        );\n    }\n\n    /**\n     * @notice  Returns the current performance fee\n     * @dev     Denominated in basis points 10000 = 100%\n     * @return  uint  The current performance fee\n     */\n    function _managerPerformanceFee() internal view returns (uint) {\n        VaultFeesStorage.Layout storage l = VaultFeesStorage.layout();\n\n        return l.managerPerformanceFee;\n    }\n\n    /**\n     * @notice  Returns the current streaming fee\n     * @dev     Denominated in basis points 10000 = 100%\n     * @return  uint  The current streaming fee\n     */\n    function _managerStreamingFee() internal view returns (uint) {\n        VaultFeesStorage.Layout storage l = VaultFeesStorage.layout();\n\n        return l.managerStreamingFee;\n    }\n\n    /**\n     * @notice  Returns the announced manager performance fee\n     * @dev     Denominated in basis points 10000 = 100%\n     * @dev     Returns 0 if there is no announced fee increase\n     * @return  uint  The announced manager performance fee\n     */\n    function _announcedManagerPerformanceFee() internal view returns (uint) {\n        VaultFeesStorage.Layout storage l = VaultFeesStorage.layout();\n\n        return l.announcedManagerPerformanceFee;\n    }\n\n    /**\n     * @notice  Returns the announced manager streaming fee\n     * @dev     Denominated in basis points 10000 = 100%\n     * @dev     Returns 0 if there is no announced fee increase\n     * @return  uint  The announced manager streaming fee\n     */\n    function _announcedManagerStreamingFee() internal view returns (uint) {\n        VaultFeesStorage.Layout storage l = VaultFeesStorage.layout();\n        return l.announcedManagerStreamingFee;\n    }\n\n    /**\n     * @notice  Returns the timestamp of the announced fee increase\n     * @dev     This is when the fee increase was announced\n     * @dev     0 if there is not annonced fee increase\n     * @return  uint  The timestamp of the announced fee increase\n     */\n    function _announcedFeeIncreaseTimestamp() internal view returns (uint) {\n        VaultFeesStorage.Layout storage l = VaultFeesStorage.layout();\n\n        return l.announcedFeeIncreaseTimestamp;\n    }\n\n    /**\n     * @notice  Returns the current referrer share\n     * @dev     Denominated in basis points 10000 = 100%\n     * @return  uint  The current referrer share\n     */\n    function _referrerShareBips() internal view returns (uint256) {\n        VaultFeesStorage.Layout storage l = VaultFeesStorage.layout();\n\n        return l.referrerShareBips;\n    }\n\n    /**\n     * @notice  Pure function which calculates the streaming fee owed\n     * @param   fee  The current streaming fee in bips\n     * @param   discount  The streaming fee discount in bips\n     * @param   lastFeeTime  The last time the fee was charged\n     * @param   totalShares  The total shares in the holding\n     * @param   timeNow  The current time\n     * @return  tokensOwed  The amount streaming fees owed denominated in shares\n     */\n    function _streamingFee(\n        uint fee,\n        uint discount,\n        uint lastFeeTime,\n        uint totalShares,\n        uint timeNow\n    ) internal pure returns (uint tokensOwed) {\n        if (lastFeeTime >= timeNow) {\n            return 0;\n        }\n\n        uint discountAdjustment = Constants.BASIS_POINTS_DIVISOR - discount;\n        uint timeSinceLastFee = timeNow - lastFeeTime;\n        tokensOwed =\n            (totalShares * fee * timeSinceLastFee * discountAdjustment) /\n            _STEAMING_FEE_DURATION /\n            Constants.BASIS_POINTS_DIVISOR /\n            Constants.BASIS_POINTS_DIVISOR;\n    }\n\n    /**\n     * @notice  Pure function which calculates the performance fee owed\n     * @param   fee  The current performance fee in bips\n     * @param   discount  The performance fee discount in bips\n     * @param   totalShares  The total shares in the holding\n     * @param   tokenPriceStart  The token price last time performance fees were charged\n     * @param   tokenPriceFinish  The current token price\n     * @return  tokensOwed  The amount performance fees owed denominated in shares\n     */\n    function _performanceFee(\n        uint fee,\n        uint discount,\n        uint totalShares,\n        uint tokenPriceStart,\n        uint tokenPriceFinish\n    ) internal pure returns (uint tokensOwed) {\n        if (tokenPriceFinish <= tokenPriceStart) {\n            return 0;\n        }\n\n        uint discountAdjustment = Constants.BASIS_POINTS_DIVISOR - discount;\n        uint priceIncrease = tokenPriceFinish - (tokenPriceStart);\n        tokensOwed =\n            (priceIncrease * fee * totalShares * discountAdjustment) /\n            tokenPriceStart /\n            Constants.BASIS_POINTS_DIVISOR /\n            Constants.BASIS_POINTS_DIVISOR;\n    }\n\n    /**\n     * @notice  Calculates the protocols share of the manager fees\n     * @param   managerFees  The total manager fees denominated in shares\n     * @param   protocolFeeBips  .\n     * @return  uint  .\n     */\n    function _protocolFee(\n        uint managerFees,\n        uint protocolFeeBips\n    ) internal pure returns (uint) {\n        return (managerFees * protocolFeeBips) / Constants.BASIS_POINTS_DIVISOR;\n    }\n}\n"
      },
      "contracts/vault-fees/VaultFeesStorage.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nlibrary VaultFeesStorage {\n    bytes32 internal constant STORAGE_SLOT =\n        keccak256('valio.storage.VaultFees');\n\n    // solhint-disable-next-line ordering\n    struct Layout {\n        uint managerStreamingFee;\n        uint managerPerformanceFee;\n        uint announcedFeeIncreaseTimestamp;\n        uint announcedManagerStreamingFee;\n        uint announcedManagerPerformanceFee;\n        uint referrerShareBips;\n    }\n\n    function layout() internal pure returns (Layout storage l) {\n        bytes32 slot = STORAGE_SLOT;\n\n        assembly {\n            l.slot := slot\n        }\n    }\n}\n"
      },
      "contracts/vault-ownership/VaultOwnershipInternal.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nimport { VaultFees } from '../vault-fees/VaultFees.sol';\nimport { VaultOwnershipStorage } from './VaultOwnershipStorage.sol';\n\nimport { ERC721BaseInternal } from '@solidstate/contracts/token/ERC721/SolidStateERC721.sol';\nimport { ERC721EnumerableInternal } from '@solidstate/contracts/token/ERC721/enumerable/ERC721Enumerable.sol';\nimport { ERC721MetadataStorage } from '@solidstate/contracts/token/ERC721/metadata/ERC721MetadataStorage.sol';\n\nimport { Constants } from '../lib/Constants.sol';\n\n/**\n * @title   VaultOwnershipInternal\n * @notice  This contract is responsible for the creation and management of holdings\n * @dev     One of the components that makes up the VaultParent\n * @dev  Each users is allowed 1 holding. The manager can have two, fee holding and personal\n * @dev  Responsibilities include: Issuing shares, burning shares, levying fees, setting referrers, and fee discounts\n */\n\ncontract VaultOwnershipInternal is\n    ERC721BaseInternal, //ERC165BaseInternal causes Linearization issue in vaultParentErc721\n    ERC721EnumerableInternal,\n    VaultFees\n{\n    // STD Struct\n    struct ReferrerInfo {\n        address referrerAddress;\n        uint referrerFees;\n        uint referrerTokenId;\n    }\n\n    uint internal constant _MANAGER_TOKEN_ID = 0;\n    uint internal constant _PROTOCOL_TOKEN_ID = 1;\n\n    uint internal constant BURN_LOCK_TIME = 24 hours;\n\n    event FeesLeviedOnHolding(\n        uint tokenId,\n        uint streamingFees,\n        uint performanceFees,\n        uint protocolFees,\n        uint referrerFees,\n        uint referrerTokenId,\n        address referrer,\n        uint managerFees,\n        uint currentUnitPrice\n    );\n\n    event ReferrerSet(uint tokenId, address referrerAddress);\n    event RefererFeesAllocated(\n        uint tokenId,\n        address referrerAddress,\n        uint referrerFees\n    );\n\n    /**\n     * @notice  Initialises stored data for the vault and creates the manager and protocol holdings\n     * @dev     Called when the vault is created\n     * @param   __name  The name of the vault\n     * @param   _symbol  The symbol/ticker of the vault\n     * @param   _manager  The managers address\n     * @param   _managerStreamingFeeBasisPoints  The managers streaming fee denominated in basis points\n     * @param   _managerPerformanceFeeBasisPoints  The managers performance fee denominated in basis points\n     * @param   _protocolAddress  The address of the protocol treasury\n     */\n    function initialize(\n        string memory __name,\n        string memory _symbol,\n        address _manager,\n        uint _managerStreamingFeeBasisPoints,\n        uint _managerPerformanceFeeBasisPoints,\n        address _protocolAddress\n    ) internal {\n        super.initialize(\n            _managerStreamingFeeBasisPoints,\n            _managerPerformanceFeeBasisPoints\n        );\n        ERC721MetadataStorage.Layout storage l = ERC721MetadataStorage.layout();\n        l.name = __name;\n        l.symbol = _symbol;\n\n        _createManagerHolding(_manager);\n        _createProtocolHolding(_protocolAddress);\n    }\n\n    /**\n     * @notice  Mints a new holding for the user and increments the tokenIdCounter\n     * @param   to  The owner of the holding\n     * @return  tokenId  The tokenId of the new holding\n     */\n    function _mint(address to) internal returns (uint256 tokenId) {\n        VaultOwnershipStorage.Layout storage l = VaultOwnershipStorage.layout();\n        tokenId = l._tokenIdCounter;\n        _safeMint(to, tokenId);\n        l._tokenIdCounter++;\n    }\n\n    /**\n     * @notice  Creates the manager holding\n     * @dev     Should only be called on vault creation\n     * @param   manager  The address of the manager (owner of the holding)\n     */\n    function _createManagerHolding(address manager) internal {\n        VaultOwnershipStorage.Layout storage l = VaultOwnershipStorage.layout();\n\n        require(\n            _exists(_MANAGER_TOKEN_ID) == false,\n            'manager holding already exists'\n        );\n        require(\n            l._tokenIdCounter == _MANAGER_TOKEN_ID,\n            'manager holding must be token 0'\n        );\n        _mint(manager);\n    }\n\n    /**\n     * @notice  Creates the protocol holding\n     * @dev     Should only be called on vault creation\n     * @param   protocolTreasury  The address of the protocol treasury (the owner of the holding)\n     */\n    function _createProtocolHolding(address protocolTreasury) internal {\n        VaultOwnershipStorage.Layout storage l = VaultOwnershipStorage.layout();\n\n        require(\n            _exists(_PROTOCOL_TOKEN_ID) == false,\n            'protcool holding already exists'\n        );\n        require(\n            l._tokenIdCounter == _PROTOCOL_TOKEN_ID,\n            'protocol holding must be token 1'\n        );\n        _mint(protocolTreasury);\n    }\n\n    /**\n     * @notice  Issues shares to the given tokenId\n     * @dev     If tokenId == 0, a new holding is created. If the tokenId exists, shares are issued to existing holding\n     * @dev     If holding exists it first levies any unpaid fees before issuing new shares\n     * @param   tokenId  The tokenId of the holding or 0\n     * @param   owner  The owner of the holding\n     * @param   shares  The number of shares to issue\n     * @param   currentUnitPrice  The current unit price of the vault (for performanceFees and averageEntry)\n     * @param   lockupTime  The lockup time that should be placed on the holding\n     * @param   protocolFeeBips  The protocol fee in basis points\n     * @param   referrerAddress  The address of the referrer\n     * @return  uint  The tokenId of the holding where the shares were issued\n     */\n    function _issueShares(\n        uint tokenId,\n        address owner,\n        uint shares,\n        uint currentUnitPrice,\n        uint lockupTime,\n        uint protocolFeeBips,\n        address referrerAddress\n    ) internal returns (uint) {\n        // Managers cannot deposit directly into their holding, they can only accrue fees there.\n        // Users or the Manger can pass tokenId == 0 (which exists) and it will create a new holding for them.\n        // This protects against a user depositing to a holding that has not been initialized yet.\n        require(_exists(tokenId), 'token does not exist');\n\n        if (tokenId == 0) {\n            tokenId = _mint(owner);\n            _setReferrer(tokenId, referrerAddress);\n        }\n\n        VaultOwnershipStorage.Layout storage l = VaultOwnershipStorage.layout();\n        VaultOwnershipStorage.Holding storage holding = l.holdings[tokenId];\n\n        if (holding.totalShares == 0) {\n            holding.streamingFee = _managerStreamingFee();\n            holding.performanceFee = _managerPerformanceFee();\n            holding.lastStreamingFeeTime = block.timestamp;\n            holding.lastPerformanceFeeUnitPrice = currentUnitPrice;\n            holding.averageEntryPrice = currentUnitPrice;\n        } else {\n            _levyFees(tokenId, currentUnitPrice, protocolFeeBips);\n            holding.averageEntryPrice = _calculateAverageEntryPrice(\n                holding.totalShares,\n                holding.averageEntryPrice,\n                shares,\n                currentUnitPrice\n            );\n        }\n\n        l.totalShares += shares;\n        holding.unlockTime = block.timestamp + lockupTime;\n        holding.totalShares += shares;\n\n        return tokenId;\n    }\n\n    /**\n     * @notice  Sets the referrer info for the holding\n     * @dev     If there is already a referrer set, it will return early\n     * @param   tokenId  The tokenId of the holding\n     * @param   referrer  The address of the referrer\n     */\n    function _setReferrer(uint tokenId, address referrer) internal {\n        if (referrer == address(0)) {\n            return;\n        }\n\n        uint referrerShareBips = _referrerShareBips();\n        if (referrerShareBips == 0) {\n            return;\n        }\n\n        VaultOwnershipStorage.Layout storage l = VaultOwnershipStorage.layout();\n        l.holdingReferrers[tokenId].referrerAddress = referrer;\n        l.holdingReferrers[tokenId].referrerShareBips = referrerShareBips;\n        emit ReferrerSet(tokenId, referrer);\n    }\n\n    /**\n     * @notice  Burns shares from the given holding/tokenId\n     * @dev     If the holding is locked, it will revert\n     * @param   tokenId  The tokenId of the holding\n     * @param   shares   The number of shares to burn\n     */\n    function _burnShares(uint tokenId, uint shares) internal {\n        VaultOwnershipStorage.Layout storage l = VaultOwnershipStorage.layout();\n\n        VaultOwnershipStorage.Holding storage holding = l.holdings[tokenId];\n        require(!_holdingLocked(tokenId), 'locked');\n        require(shares <= holding.totalShares, 'not enough shares');\n        holding.lastBurnTime = block.timestamp;\n        holding.totalShares -= shares;\n        l.totalShares -= shares;\n    }\n\n    /**\n     * @notice  Levies streaming fees and performance fees against the holding\n     * @notice  and distributes them to the protocol, manager, and referrer\n     * @dev     If the manager has changed the fees, they will be updated here\n     * @dev     once fees are harvested at the current rate\n     * @param   tokenId  .\n     * @param   currentUnitPrice  .\n     * @param   protocolFeeBips  .\n     */\n    function _levyFees(\n        uint tokenId,\n        uint currentUnitPrice,\n        uint protocolFeeBips\n    ) internal {\n        if (isSystemToken(tokenId)) {\n            return;\n        }\n\n        // This modifies the holding, subtracting the fees from totalShares\n        (uint streamingFees, uint performanceFees) = _levyFeesOnHolding(\n            tokenId,\n            _managerStreamingFee(),\n            _managerPerformanceFee(),\n            currentUnitPrice\n        );\n\n        uint protocolFees = _protocolFee(\n            streamingFees + performanceFees,\n            protocolFeeBips\n        );\n\n        // Stack To Deep using struct\n        ReferrerInfo memory rInfo = _getReferrerInfoAndCalculateFees(\n            tokenId,\n            streamingFees + performanceFees,\n            currentUnitPrice\n        );\n\n        uint managerFees = (streamingFees + performanceFees) -\n            protocolFees -\n            rInfo.referrerFees;\n\n        require(\n            protocolFees + managerFees + rInfo.referrerFees ==\n                streamingFees + performanceFees,\n            'fee math'\n        );\n\n        // Stack To Deep\n        {\n            VaultOwnershipStorage.Layout storage l = VaultOwnershipStorage\n                .layout();\n\n            if (rInfo.referrerFees > 0) {\n                l.holdings[rInfo.referrerTokenId].totalShares += rInfo\n                    .referrerFees;\n            }\n\n            l.holdings[_PROTOCOL_TOKEN_ID].totalShares += protocolFees;\n            l.holdings[_MANAGER_TOKEN_ID].totalShares += managerFees;\n        }\n\n        emit FeesLeviedOnHolding(\n            tokenId,\n            streamingFees,\n            performanceFees,\n            protocolFees,\n            rInfo.referrerFees,\n            rInfo.referrerTokenId,\n            rInfo.referrerAddress,\n            managerFees,\n            currentUnitPrice\n        );\n    }\n\n    /**\n     * @notice  Calculates the referrers share of fees\n     * @dev     Creates a new holding for the referrer if they do not have one\n     * @param   tokenId  the tokenId of the holding thats paying referral fees\n     * @param   totalFees  the total fees being charged to the above holding\n     * @param   currentUnitPrice  the current unit price of the shares\n     * @return  referrerInfo  The referrer info including referrers tokenId\n     */\n    function _getReferrerInfoAndCalculateFees(\n        uint tokenId,\n        uint totalFees,\n        uint currentUnitPrice\n    ) internal returns (ReferrerInfo memory referrerInfo) {\n        VaultOwnershipStorage.Layout storage l = VaultOwnershipStorage.layout();\n\n        VaultOwnershipStorage.HoldingReferrer storage referrer = l\n            .holdingReferrers[tokenId];\n\n        referrerInfo.referrerAddress = referrer.referrerAddress;\n        if (referrerInfo.referrerAddress == address(0)) {\n            return referrerInfo;\n        }\n\n        referrerInfo.referrerFees =\n            (totalFees * referrer.referrerShareBips) /\n            Constants.BASIS_POINTS_DIVISOR;\n\n        if (referrerInfo.referrerFees == 0) {\n            return referrerInfo;\n        }\n\n        if (_balanceOf(referrer.referrerAddress) == 0) {\n            // Create a new holding for the referrer with 0 shares\n            referrerInfo.referrerTokenId = _issueShares(\n                0, // TokenId == 0 == new holding\n                referrerInfo.referrerAddress, // owner\n                0, // number of shares\n                currentUnitPrice,\n                0, // lockupTime\n                0, // protocolFeeBips\n                address(0)\n            );\n        } else {\n            referrerInfo.referrerTokenId = _tokenOfOwnerByIndex(\n                referrerInfo.referrerAddress,\n                0\n            );\n        }\n    }\n\n    /**\n     * @notice  Levies streaming fees and performance fees against the holding and returns the amount levied\n     * @dev     If the manager has changed the fees, they will be updated here,\n     * @dev     once fees are harvested at the current rate\n     * @dev     The assignment of these fees to the manager, protocol and referrer happens upstream\n     * @param   tokenId  the tokenId of the holding\n     * @param   newStreamingFee    the managers new streamingFee\n     * @param   newPerformanceFee  the managers new performanceFee\n     * @param   currentUnitPrice   the current unit price of the shares\n     * @return  streamingFees    The amount of streaming fees levied\n     * @return  performanceFees  The amount of performance fees levied\n     */\n    function _levyFeesOnHolding(\n        uint tokenId,\n        uint newStreamingFee,\n        uint newPerformanceFee,\n        uint currentUnitPrice\n    ) internal returns (uint streamingFees, uint performanceFees) {\n        VaultOwnershipStorage.Layout storage l = VaultOwnershipStorage.layout();\n        VaultOwnershipStorage.Holding storage holding = l.holdings[tokenId];\n\n        uint initialTotalShares = holding.totalShares;\n\n        holding.lastManagerFeeLevyTime = block.timestamp;\n\n        (streamingFees, performanceFees) = _calculateUnpaidFees(\n            tokenId,\n            currentUnitPrice\n        );\n\n        if (streamingFees > 0 || holding.streamingFee != newStreamingFee) {\n            holding.lastStreamingFeeTime = block.timestamp;\n        }\n\n        if (\n            performanceFees > 0 ||\n            (holding.performanceFee != newPerformanceFee &&\n                currentUnitPrice > holding.lastPerformanceFeeUnitPrice)\n        ) {\n            holding.lastPerformanceFeeUnitPrice = currentUnitPrice;\n        }\n\n        if (holding.streamingFee != newStreamingFee) {\n            holding.streamingFee = newStreamingFee;\n        }\n\n        if (holding.performanceFee != newPerformanceFee) {\n            holding.performanceFee = newPerformanceFee;\n        }\n\n        holding.totalShares -= streamingFees + performanceFees;\n\n        require(\n            holding.totalShares + streamingFees + performanceFees ==\n                initialTotalShares,\n            'check failed'\n        );\n\n        return (streamingFees, performanceFees);\n    }\n\n    /**\n     * @notice  Allows the manager to set a fee discount for a holding\n     * @dev     The discount is denominated in basis points\n     * @param   tokenId  The tokenId of the holding\n     * @param   streamingFeeDiscount  the discount on the streaming fee\n     * @param   performanceFeeDiscount  the discount on the performance fee\n     */\n    function _setDiscountForHolding(\n        uint tokenId,\n        uint streamingFeeDiscount,\n        uint performanceFeeDiscount\n    ) internal {\n        require(\n            streamingFeeDiscount <= Constants.BASIS_POINTS_DIVISOR,\n            'invalid streamingFeeDiscount'\n        );\n        require(\n            performanceFeeDiscount <= Constants.BASIS_POINTS_DIVISOR,\n            'invalid performanceFeeDiscount'\n        );\n\n        VaultOwnershipStorage.Layout storage l = VaultOwnershipStorage.layout();\n        VaultOwnershipStorage.Holding storage holding = l.holdings[tokenId];\n\n        holding.streamingFeeDiscount = streamingFeeDiscount;\n        holding.performanceFeeDiscount = performanceFeeDiscount;\n    }\n\n    /**\n     * @notice  Returns the holding for the given tokenId\n     * @param   tokenId  The tokenId of the holding\n     * @return  VaultOwnershipStorage.Holding  The holding\n     */\n    function _holdings(\n        uint tokenId\n    ) internal view returns (VaultOwnershipStorage.Holding memory) {\n        VaultOwnershipStorage.Layout storage l = VaultOwnershipStorage.layout();\n        return l.holdings[tokenId];\n    }\n\n    /**\n     * @notice  Returns of the holding is under lockup\n     * @param   tokenId  The tokenId of the holding\n     * @return  bool  True if the holding is locked\n     */\n    function _holdingLocked(uint tokenId) internal view returns (bool) {\n        VaultOwnershipStorage.Layout storage l = VaultOwnershipStorage.layout();\n\n        VaultOwnershipStorage.Holding storage holding = l.holdings[tokenId];\n        if (block.timestamp < holding.unlockTime) {\n            return true;\n        }\n\n        return false;\n    }\n\n    /**\n     * @notice  Returns the referrer for the given tokenId\n     * @param   tokenId  The tokenId of the holding\n     * @return  VaultOwnershipStorage.HoldingReferrer  The referrer info\n     */\n    function _holdingReferrer(\n        uint tokenId\n    ) internal view returns (VaultOwnershipStorage.HoldingReferrer memory) {\n        VaultOwnershipStorage.Layout storage l = VaultOwnershipStorage.layout();\n        return l.holdingReferrers[tokenId];\n    }\n\n    /**\n     * @notice  Returns the total number of shares across all holdings\n     * @dev     This is used to calculate the unit price of the vault and determine a holdings portion\n     * @return  uint  The total number of shares\n     */\n    function _totalShares() internal view returns (uint) {\n        VaultOwnershipStorage.Layout storage l = VaultOwnershipStorage.layout();\n        return l.totalShares;\n    }\n\n    /**\n     * @notice  Returns the number of owed fees for the given tokenId and the given tokenPrice\n     * @dev     This is used to calculate the amount of fees owed to the manager, protocol, and referrer\n     * @param   tokenId  The tokenId of the holding\n     * @param   currentUnitPrice  The current unit price of the vault\n     * @return  streamingFees  The amount of streaming fees owed\n     * @return  performanceFees  The amount of performance fees owed\n     */\n    function _calculateUnpaidFees(\n        uint tokenId,\n        uint currentUnitPrice\n    ) internal view returns (uint streamingFees, uint performanceFees) {\n        if (isSystemToken(tokenId)) {\n            return (0, 0);\n        }\n\n        VaultOwnershipStorage.Layout storage l = VaultOwnershipStorage.layout();\n        VaultOwnershipStorage.Holding storage holding = l.holdings[tokenId];\n\n        uint initialTotalShares = holding.totalShares;\n\n        streamingFees = _streamingFee(\n            holding.streamingFee,\n            holding.streamingFeeDiscount,\n            holding.lastStreamingFeeTime,\n            initialTotalShares,\n            block.timestamp\n        );\n\n        performanceFees = _performanceFee(\n            holding.performanceFee,\n            holding.performanceFeeDiscount,\n            // We levy performance fees after levying streamingFees\n            initialTotalShares - streamingFees,\n            holding.lastPerformanceFeeUnitPrice,\n            currentUnitPrice\n        );\n    }\n\n    /**\n     * @notice  Returns the name of the Vault\n     * @dev     This is used to identify the vault in the UI\n     * @return  string  The name of the vault\n     */\n    function _name() internal view virtual returns (string memory) {\n        return ERC721MetadataStorage.layout().name;\n    }\n\n    /**\n     * @notice  Returns the average entry price based on the price paid for existing shares\n     * @notice  and the price paid for new shares\n     * @param   currentShares  The number of shares currently held\n     * @param   previousPrice  The average price paid for the above shares\n     * @param   newShares  The number of new shares being issued\n     * @param   newPrice  The price paid for the new shares\n     * @return  uint  The average price paid for all shares\n     */\n    function _calculateAverageEntryPrice(\n        uint currentShares,\n        uint previousPrice,\n        uint newShares,\n        uint newPrice\n    ) internal pure returns (uint) {\n        return\n            ((currentShares * previousPrice) + (newShares * newPrice)) /\n            (currentShares + newShares);\n    }\n\n    /**\n     * @notice  Returns if the tokenId is a system token\n     * @dev     System tokens are the manager and protocol holdings\n     * @param   tokenId  The tokenId of the holding\n     * @return  bool  True if the tokenId is a system token\n     */\n    function isSystemToken(uint tokenId) internal pure returns (bool) {\n        return tokenId == _PROTOCOL_TOKEN_ID || tokenId == _MANAGER_TOKEN_ID;\n    }\n}\n"
      },
      "contracts/vault-ownership/VaultOwnershipStorage.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nlibrary VaultOwnershipStorage {\n    bytes32 internal constant STORAGE_SLOT =\n        keccak256('valio.storage.VaultOwnership');\n\n    // TODO: Move to interface\n    // solhint-disable-next-line ordering\n    struct Holding {\n        uint totalShares;\n        uint lastStreamingFeeTime;\n        uint lastPerformanceFeeUnitPrice;\n        uint streamingFeeDiscount;\n        uint performanceFeeDiscount;\n        uint streamingFee;\n        uint performanceFee;\n        uint unlockTime;\n        uint averageEntryPrice;\n        uint lastManagerFeeLevyTime;\n        uint lastBurnTime;\n    }\n\n    struct HoldingReferrer {\n        address referrerAddress;\n        uint256 referrerShareBips;\n    }\n\n    // solhint-disable-next-line ordering\n    struct Layout {\n        // The manager is issued token 0; The protocol is issued token 1; all other tokens are issued to investors\n        // All fees are levied to token 0 and a portion to token 1;\n        // tokenId to Holding\n        mapping(uint => Holding) holdings;\n        uint totalShares;\n        uint256 _tokenIdCounter;\n        // tokenId -> referrer\n        mapping(uint => HoldingReferrer) holdingReferrers;\n    }\n\n    function layout() internal pure returns (Layout storage l) {\n        bytes32 slot = STORAGE_SLOT;\n\n        assembly {\n            l.slot := slot\n        }\n    }\n}\n"
      },
      "contracts/vault-parent/IVaultParentInvestor.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\ninterface IVaultParentInvestor {\n    function withdrawMultiChain(\n        uint tokenId,\n        uint amount,\n        uint[] memory lzFees\n    ) external payable;\n\n    function requestTotalValueUpdateMultiChain(\n        uint[] memory lzFees\n    ) external payable;\n}\n"
      },
      "contracts/vault-parent/IVaultParentManager.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\ninterface IVaultParentManager {\n    function requestBridgeToChain(\n        uint16 dstChainId,\n        address asset,\n        uint256 amount,\n        uint256 minAmountOut,\n        uint\n    ) external payable;\n\n    function requestCreateChild(uint16 newChainId, uint) external payable;\n\n    function sendBridgeApproval(uint16 dstChainId, uint) external payable;\n\n    function changeManagerMultiChain(\n        address newManager,\n        uint[] memory lzFees\n    ) external payable;\n\n    function setDiscountForHolding(\n        uint256 tokenId,\n        uint256 streamingFeeDiscount,\n        uint256 performanceFeeDiscount\n    ) external;\n}\n"
      },
      "contracts/vault-parent/VaultParent.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nimport { VaultParentTransport } from './VaultParentTransport.sol';\nimport { VaultParentInvestor } from './VaultParentInvestor.sol';\nimport { VaultParentManager } from './VaultParentManager.sol';\nimport { VaultParentErc721 } from './VaultParentErc721.sol';\nimport { VaultParentInternal } from './VaultParentInternal.sol';\nimport { VaultBaseExternal } from '../vault-base/VaultBaseExternal.sol';\nimport { VaultOwnershipInternal } from '../vault-ownership/VaultOwnershipInternal.sol';\nimport { IRedeemerEvents } from '../redeemers/IRedeemerEvents.sol';\nimport { IExecutorEvents } from '../executors/IExecutorEvents.sol';\n\nimport { SolidStateERC721 } from '@solidstate/contracts/token/ERC721/SolidStateERC721.sol';\nimport { ERC721MetadataInternal } from '@solidstate/contracts/token/ERC721/metadata/ERC721MetadataInternal.sol';\nimport { ERC721BaseInternal, ERC165Base } from '@solidstate/contracts/token/ERC721/SolidStateERC721.sol';\n\n/**\n * @title   VaultParent\n * @dev     Not deployed as It's to large, never deploy for tests always use diamond\n * @dev     The components inherited make up the VaultParentDiamond\n * @notice  ONLY used to generate the ABI and for test interface\n */\n\ncontract VaultParent is\n    VaultParentInvestor,\n    VaultParentErc721,\n    VaultParentManager,\n    VaultParentTransport,\n    VaultBaseExternal,\n    IRedeemerEvents,\n    IExecutorEvents\n{\n    function _beforeTokenTransfer(\n        address from,\n        address to,\n        uint256 tokenId\n    ) internal override(VaultParentErc721, VaultParentInternal) {\n        super._beforeTokenTransfer(from, to, tokenId);\n    }\n\n    /**\n     * @notice ERC721 hook: revert if value is included in external approve function call\n     * @inheritdoc ERC721BaseInternal\n     */\n    function _handleApproveMessageValue(\n        address operator,\n        uint256 tokenId,\n        uint256 value\n    ) internal virtual override(VaultParentErc721, ERC721BaseInternal) {\n        if (value > 0) revert SolidStateERC721__PayableApproveNotSupported();\n        super._handleApproveMessageValue(operator, tokenId, value);\n    }\n\n    /**\n     * @notice ERC721 hook: revert if value is included in external transfer function call\n     * @inheritdoc ERC721BaseInternal\n     */\n    function _handleTransferMessageValue(\n        address from,\n        address to,\n        uint256 tokenId,\n        uint256 value\n    ) internal virtual override(VaultParentErc721, ERC721BaseInternal) {\n        if (value > 0) revert SolidStateERC721__PayableTransferNotSupported();\n        super._handleTransferMessageValue(from, to, tokenId, value);\n    }\n\n    function _name()\n        internal\n        view\n        override(VaultOwnershipInternal, VaultParentInvestor, VaultParentErc721)\n        returns (string memory)\n    {\n        return VaultOwnershipInternal._name();\n    }\n}\n"
      },
      "contracts/vault-parent/VaultParentErc721.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nimport { SolidStateERC721, ERC721BaseInternal } from '@solidstate/contracts/token/ERC721/SolidStateERC721.sol';\nimport { ERC721MetadataInternal } from '@solidstate/contracts/token/ERC721/metadata/ERC721MetadataInternal.sol';\nimport { IERC165 } from '@solidstate/contracts/interfaces/IERC165.sol';\nimport { IERC721 } from '@solidstate/contracts/interfaces/IERC721.sol';\n\nimport { ITransport } from '../transport/ITransport.sol';\nimport { Registry } from '../registry/Registry.sol';\nimport { RegistryStorage } from '../registry/RegistryStorage.sol';\nimport { VaultParentStorage } from './VaultParentStorage.sol';\nimport { VaultParentInternal } from './VaultParentInternal.sol';\nimport { VaultBaseInternal } from '../vault-base/VaultBaseInternal.sol';\nimport { VaultOwnershipInternal } from '../vault-ownership/VaultOwnershipInternal.sol';\nimport { VaultRiskProfile } from '../vault-base/IVaultRiskProfile.sol';\nimport { Constants } from '../lib/Constants.sol';\n\n/**\n * @title   VaultParentErc721\n * @dev     One of the components of the VaultParent\n * @dev     Exposes `initialize` function to set up the VaultParent\n * @notice  Used to expost the ERC721 interface to the VaultParent\n */\n\ncontract VaultParentErc721 is SolidStateERC721, VaultParentInternal {\n    /**\n     * @notice  Initializes the VaultParent\n     * @dev     Calls all other superclass initializers\n     * @param   __name  The name of the Vault\n     * @param   __symbol  The symbol of the Vault aka Ticker\n     * @param   __manager  The manager of the Vault\n     * @param   __managerStreamingFeeBasisPoints  the manager streaming fee in basis points\n     * @param   __managerPerformanceFeeBasisPoints  the manager performance fee in basis points\n     * @param   __riskProfile  The risk profile of the Vault\n     * @param   __registry  The valio registry\n     */\n    function initialize(\n        string memory __name,\n        string memory __symbol,\n        address __manager,\n        uint __managerStreamingFeeBasisPoints,\n        uint __managerPerformanceFeeBasisPoints,\n        VaultRiskProfile __riskProfile,\n        Registry __registry\n    ) external {\n        require(_vaultId() == 0, 'already initialized');\n\n        bytes32 vaultId = keccak256(\n            abi.encodePacked(__registry.chainId(), address(this))\n        );\n        _setVaultId(vaultId);\n        VaultBaseInternal.initialize(__registry, __manager, __riskProfile);\n        VaultOwnershipInternal.initialize(\n            __name,\n            __symbol,\n            __manager,\n            __managerStreamingFeeBasisPoints,\n            __managerPerformanceFeeBasisPoints,\n            __registry.protocolTreasury()\n        );\n\n        _setSupportsInterface(type(IERC165).interfaceId, true);\n        _setSupportsInterface(type(IERC721).interfaceId, true);\n    }\n\n    /**\n     * @notice  ERC721 hook: reverts, transfers are disabled\n     */\n    function _beforeTokenTransfer(\n        address from,\n        address to,\n        uint256 tokenId\n    ) internal virtual override(SolidStateERC721, VaultParentInternal) {\n        VaultParentInternal._beforeTokenTransfer(from, to, tokenId);\n    }\n\n    /**\n     * @notice ERC721 hook: revert if value is included in external approve function call\n     * @inheritdoc ERC721BaseInternal\n     */\n    function _handleApproveMessageValue(\n        address operator,\n        uint256 tokenId,\n        uint256 value\n    ) internal virtual override(SolidStateERC721, ERC721BaseInternal) {\n        if (value > 0) revert SolidStateERC721__PayableApproveNotSupported();\n        super._handleApproveMessageValue(operator, tokenId, value);\n    }\n\n    /**\n     * @notice ERC721 hook: revert if value is included in external transfer function call\n     * @inheritdoc ERC721BaseInternal\n     */\n    function _handleTransferMessageValue(\n        address from,\n        address to,\n        uint256 tokenId,\n        uint256 value\n    ) internal virtual override(SolidStateERC721, ERC721BaseInternal) {\n        if (value > 0) revert SolidStateERC721__PayableTransferNotSupported();\n        super._handleTransferMessageValue(from, to, tokenId, value);\n    }\n\n    /**\n     * @notice  Returns the name of the Vault\n     * @return  string  name\n     */\n    function _name()\n        internal\n        view\n        virtual\n        override(VaultOwnershipInternal, ERC721MetadataInternal)\n        returns (string memory)\n    {\n        return VaultOwnershipInternal._name();\n    }\n}\n"
      },
      "contracts/vault-parent/VaultParentInternal.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nimport { VaultBaseInternal } from '../vault-base/VaultBaseInternal.sol';\nimport { VaultOwnershipInternal } from '../vault-ownership/VaultOwnershipInternal.sol';\nimport { VaultParentStorage } from './VaultParentStorage.sol';\nimport { IVaultParentManager } from './IVaultParentManager.sol';\nimport { IVaultParentInvestor } from './IVaultParentInvestor.sol';\n\nimport { GasFunctionType } from '../transport/ITransport.sol';\n\nimport { Constants } from '../lib/Constants.sol';\n\n/**\n * @title   VaultParentInternal\n * @notice  Logic shared between other VaultParent components\n * @dev     Should be split up\n */\n\ncontract VaultParentInternal is VaultOwnershipInternal, VaultBaseInternal {\n    /**\n     * @notice  Reverts if a brige is in progress\n     * @dev     This means funds could be inflight\n     */\n    modifier noBridgeInProgress() {\n        require(!_bridgeInProgress(), 'bridge in progress');\n        _;\n    }\n\n    /**\n     * @notice  Reverts if a vault is closed\n     * @dev     This means users can no longer deposit\n     */\n    modifier vaultNotClosed() {\n        require(!_vaultClosed(), 'vault closed');\n        _;\n    }\n\n    /**\n     * @notice  Blocks transfers of tokens\n     * @dev     The managers token can be transferred to a new manager internally\n     * @param   from  the previous token owner\n     * @param   to  the new token owner\n     * @param   tokenId  the token id\n     */\n    function _beforeTokenTransfer(\n        address from,\n        address to,\n        uint256 tokenId\n    ) internal virtual override {\n        super._beforeTokenTransfer(from, to, tokenId);\n\n        // If minting just return\n        if (from == address(0)) {\n            return;\n        }\n        // When using changeManager(), allow transfer to new manager\n        if (tokenId == _MANAGER_TOKEN_ID) {\n            require(to == _manager(), 'must use changeManager');\n            return;\n        }\n\n        revert('transfers disabled');\n    }\n\n    /**\n     * @notice  Returns true of a withdraw is in progress\n     * @dev     This means there are outstanding withdraw requests being processed\n     * @dev     When a child vault receives a withdraw request, once complete it sends back a withdraw complete message\n     * @dev     All outstanding withdraws must be complete this will return false\n     * @return  bool  true if a withdraw is in progress\n     */\n    function _withdrawInProgress() internal view returns (bool) {\n        VaultParentStorage.Layout storage l = VaultParentStorage.layout();\n\n        return l.withdrawsInProgress > 0;\n    }\n\n    /**\n     * @notice  Returns true if a bridge is in progress\n     * @dev     This means funds could be inflight\n     * @return  bool  true if a bridge is in progress\n     */\n    function _bridgeInProgress() internal view returns (bool) {\n        VaultParentStorage.Layout storage l = VaultParentStorage.layout();\n        return l.bridgeInProgress;\n    }\n\n    /**\n     * @notice  Returns which child chain is approved to bridge\n     * @dev     The child chain must bridge or cancel the bridge to remove the approval\n     * @return  uint  the lz child chain id\n     */\n    function _bridgeApprovedFor() internal view returns (uint16) {\n        VaultParentStorage.Layout storage l = VaultParentStorage.layout();\n        return l.bridgeApprovedFor;\n    }\n\n    /**\n     * @notice  Returns if the vault has any active child vaults\n     * @dev     An active child vault is one that has received funds at some point\n     * @dev     Currently once a childVault is active, its always active\n     * @return  bool  .\n     */\n    function _hasActiveChildren() internal view returns (bool) {\n        VaultParentStorage.Layout storage l = VaultParentStorage.layout();\n\n        for (uint8 i = 0; i < l.childChains.length; i++) {\n            if (!_childIsInactive(l.childChains[i])) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    /**\n\n\n    /**\n     * @notice  Returns the lz fee for the give function\n     * @dev     This is a helper method for the frontend\n     * @dev     We use the sighash of the intended function call to identify the action\n     * @param   sigHash  The sighash of the intended function call\n     * @param   chainId  The destination lz chain id\n     * @return  fee  The lz fee for the message + destination gas\n     */\n    function _getLzFee(\n        bytes4 sigHash,\n        uint16 chainId\n    ) internal view returns (uint fee) {\n        if (sigHash == IVaultParentManager.requestBridgeToChain.selector) {\n            fee = _bridgeQuote(chainId);\n        } else if (sigHash == IVaultParentManager.requestCreateChild.selector) {\n            (fee, ) = _registry().transport().getLzFee(\n                GasFunctionType.createChildRequiresReturnMessage,\n                chainId\n            );\n        } else if (\n            sigHash ==\n            IVaultParentInvestor.requestTotalValueUpdateMultiChain.selector\n        ) {\n            if (_childIsInactive(chainId)) {\n                return 0;\n            }\n            (fee, ) = _registry().transport().getLzFee(\n                GasFunctionType.getVaultValueRequiresReturnMessage,\n                chainId\n            );\n        } else if (\n            sigHash == IVaultParentInvestor.withdrawMultiChain.selector\n        ) {\n            if (_childIsInactive(chainId)) {\n                return 0;\n            }\n            (fee, ) = _registry().transport().getLzFee(\n                GasFunctionType.withdrawRequiresReturnMessage,\n                chainId\n            );\n        } else if (sigHash == IVaultParentManager.sendBridgeApproval.selector) {\n            (fee, ) = _registry().transport().getLzFee(\n                GasFunctionType.sendBridgeApprovalNoReturnMessage,\n                chainId\n            );\n        } else {\n            (fee, ) = _registry().transport().getLzFee(\n                GasFunctionType.standardNoReturnMessage,\n                chainId\n            );\n        }\n    }\n\n    /**\n     * @notice  Returns the lz fees for the given function on all child chains\n     * @dev     This is a helper method for the frontend\n     * @dev     We use the sighash of the intended function call to identify the action\n     * @param   sigHash  The sighash of the intended function call\n     * @param   chainIds  The destination lz chain ids\n     * @return  fees  The lz fees for the message + destination gas\n     * @return  totalSendFee  The total lz fee for the message + destination gas\n     */\n    function _getLzFeesMultiChain(\n        bytes4 sigHash,\n        uint16[] memory chainIds\n    ) internal view returns (uint[] memory fees, uint256 totalSendFee) {\n        fees = new uint[](chainIds.length);\n        for (uint i = 0; i < chainIds.length; i++) {\n            fees[i] = _getLzFee(sigHash, chainIds[i]);\n            totalSendFee += fees[i];\n        }\n    }\n\n    /**\n     * @notice  Returns the fee for executing a bridge\n     * @dev     Currently this is stargate, but could be different in the future\n     * @param   dstChainId  The destination lz chain id\n     * @return  fee  The stargate fee for the bridge\n     */\n    function _bridgeQuote(uint16 dstChainId) internal view returns (uint fee) {\n        VaultParentStorage.Layout storage l = VaultParentStorage.layout();\n\n        address dstVault = l.children[dstChainId];\n        require(dstVault != address(0), 'no dst vault');\n\n        fee = _registry().transport().getBridgeAssetQuote(\n            dstChainId,\n            dstVault,\n            _registry().chainId(),\n            address(this)\n        );\n    }\n\n    /**\n     * @notice  Returns if a child is not active\n     * @dev     The child active state was added after the initial release\n     * @dev     Therefore inverse storage flag is used\n     * @param   chainId  The lz chain id of the child\n     * @return  bool  false if the child is active\n     */\n    function _childIsInactive(uint16 chainId) internal view returns (bool) {\n        VaultParentStorage.Layout storage l = VaultParentStorage.layout();\n\n        return l.childIsInactive[chainId];\n    }\n\n    /**\n     * @notice  Returns if the vault is in sync\n     * @dev     This means the vault has the latest value for all child vaults\n     * @return  bool  true if the vault is in sync\n     */\n    function _inSync() internal view returns (bool) {\n        VaultParentStorage.Layout storage l = VaultParentStorage.layout();\n\n        for (uint8 i = 0; i < l.childChains.length; i++) {\n            if (_childIsInactive(l.childChains[i])) {\n                continue;\n            }\n            if (_isNotStale(l.chainTotalValues[l.childChains[i]].lastUpdate)) {\n                continue;\n            } else {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    /**\n     * @notice  Returns the total value of the vault across all chains (AUM)\n     * @dev     Will revert if the child vault values are stale\n     * @return  minValue  the min value\n     * @return  maxValue  the max value\n     * @return  hasHardDeprecatedAsset  if the vault has a hard deprecated asse\n     */\n    function _totalValueAcrossAllChains()\n        internal\n        view\n        returns (uint minValue, uint maxValue, bool hasHardDeprecatedAsset)\n    {\n        VaultParentStorage.Layout storage l = VaultParentStorage.layout();\n\n        (minValue, maxValue, hasHardDeprecatedAsset) = _getVaultValue();\n\n        for (uint8 i = 0; i < l.childChains.length; i++) {\n            if (_childIsInactive(l.childChains[i])) {\n                continue;\n            }\n            require(\n                _isNotStale(l.chainTotalValues[l.childChains[i]].lastUpdate),\n                'stale'\n            );\n            minValue += l.chainTotalValues[l.childChains[i]].minValue;\n            maxValue += l.chainTotalValues[l.childChains[i]].maxValue;\n            if (l.chainTotalValues[l.childChains[i]].hasHardDeprecatedAsset) {\n                hasHardDeprecatedAsset = true;\n            }\n        }\n    }\n\n    /**\n     * @notice  Returns the unitPrice of each share in the vault (AUM/shares)\n     * @dev     This is returned at Contants.VAULT_PRECISION\n     * @return  minPrice  The min price of each share\n     * @return  maxPrice  The max price of each share\n     */\n    function _unitPrice() internal view returns (uint minPrice, uint maxPrice) {\n        uint totalShares = _totalShares();\n        (uint minValue, uint maxValue, ) = _totalValueAcrossAllChains();\n        // Avoids divide by 0;\n        if (totalShares == 0 && maxValue == 0) {\n            return (0, 0);\n        }\n        // This should never occur. It's a safety check\n        if (totalShares == 0 && maxValue != 0) {\n            revert('Vault Error: ttsnvl');\n        }\n\n        minPrice = _unitPrice(minValue, totalShares);\n        maxPrice = _unitPrice(maxValue, totalShares);\n    }\n\n    /**\n     * @notice  Returns the lzChainId of the child at the given index\n     * @dev     We store a list of lzChainId[] for the child vaults created\n     * @param   index  The index\n     * @return  chainId  The lz chain id\n     */\n    function _childChains(uint index) internal view returns (uint16 chainId) {\n        VaultParentStorage.Layout storage l = VaultParentStorage.layout();\n\n        return l.childChains[index];\n    }\n\n    /**\n     * @notice  The list of lz chainIds for all child vaults created\n     * @dev     We store a list of lzChainId[] for the child vaults created\n     * @return  uint16[]  The list of lz chainIds\n     */\n    function _allChildChains() internal view returns (uint16[] memory) {\n        VaultParentStorage.Layout storage l = VaultParentStorage.layout();\n\n        return l.childChains;\n    }\n\n    /**\n     * @notice  Returns the child vault address for the given lz chain id\n     * @dev     We store a mapping of lzChainId => childVaultAddress\n     * @param   chainId  The lz chain id\n     * @return  address  The child vault address\n     */\n    function _children(uint16 chainId) internal view returns (address) {\n        return VaultParentStorage.layout().children[chainId];\n    }\n\n    /**\n     * @notice  Returns the time until the oldest child vault value expires\n     * @dev     This should be named better vaultVaultTimeUntilExpiry\n     * @return  uint  The time until the oldest child vault value expires\n     */\n    function _timeUntilExpiry() internal view returns (uint) {\n        VaultParentStorage.Layout storage l = VaultParentStorage.layout();\n        uint timeTillExpiry;\n        for (uint8 i = 0; i < l.childChains.length; i++) {\n            uint expiryTime = _timeUntilExpiry(\n                l.chainTotalValues[l.childChains[i]].lastUpdate\n            );\n            // The shortest expiry time is the time until expiry\n            if (expiryTime == 0) {\n                return 0;\n            } else {\n                if (expiryTime < timeTillExpiry || timeTillExpiry == 0) {\n                    timeTillExpiry = expiryTime;\n                }\n            }\n        }\n        return timeTillExpiry;\n    }\n\n    /**\n     * @notice  Returns if the vault is closed\n     * @dev     This means users can no longer deposit\n     * @return  bool  true if the vault is closed\n     */\n    function _vaultClosed() internal view returns (bool) {\n        VaultParentStorage.Layout storage l = VaultParentStorage.layout();\n\n        return l.vaultClosed;\n    }\n\n    /**\n     * @notice  Returns how long until the given lastUpdate time is stale\n     * @dev     This is the time until the value of the child vault is stale\n     * @param   lastUpdate  The last time the child vault value was updated\n     * @return  uint  The time until the value is stale\n     */\n    function _timeUntilExpiry(uint lastUpdate) internal view returns (uint) {\n        uint expiry = lastUpdate + _registry().livelinessThreshold();\n        if (expiry > block.timestamp) {\n            return expiry - block.timestamp;\n        } else {\n            return 0;\n        }\n    }\n\n    /**\n     * @notice  Returns if the given lastUpdate time is not yet stale\n     * @dev     Should have been isStale\n     * @param   lastUpdate  The last time the child vault value was updated\n     * @return  bool  true if the value is not stale\n     */\n    function _isNotStale(uint lastUpdate) internal view returns (bool) {\n        return lastUpdate > block.timestamp - _registry().livelinessThreshold();\n    }\n\n    /**\n     * @notice  Returns if the given tokenId requires a sync to harvest fees\n     * @param   tokenId  The tokenId of holding\n     * @return  bool  true if the tokenId requires a sync to harvest fees\n     */\n    function _requiresSyncForFees(uint tokenId) internal view returns (bool) {\n        if (!_hasActiveChildren() || !_requiresUnitPrice(tokenId)) {\n            return false;\n        }\n        return true;\n    }\n\n    /**\n     * @notice  Returns if the given tokenId requires a unit price to harvest fees\n     * @dev     False if the manager has no performamce fee or the tokenId is a system token\n     * @param   tokenId  The tokenId of holding\n     * @return  bool  true if the tokenId requires a unit price to harvest fees\n     */\n    function _requiresUnitPrice(uint tokenId) internal view returns (bool) {\n        if (isSystemToken(tokenId)) {\n            return false;\n        }\n        if (\n            (_managerPerformanceFee() == 0 &&\n                _holdings(tokenId).performanceFee == 0)\n        ) {\n            return false;\n        }\n\n        return true;\n    }\n\n    /**\n     * @notice  Calculates the unitPrice from the given AUM and Shares\n     * @param   totalValueAcrossAllChains  The vaults total aum\n     * @param   totalShares  The total outstanding shares\n     * @return  price  The unit price of each share\n     */\n    function _unitPrice(\n        uint totalValueAcrossAllChains,\n        uint totalShares\n    ) internal pure returns (uint price) {\n        price =\n            (totalValueAcrossAllChains * Constants.VAULT_PRECISION) /\n            totalShares;\n    }\n}\n"
      },
      "contracts/vault-parent/VaultParentInvestor.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nimport { ITransport } from '../transport/ITransport.sol';\nimport { Constants } from '../lib/Constants.sol';\nimport { VaultParentStorage } from './VaultParentStorage.sol';\nimport { VaultParentInternal } from './VaultParentInternal.sol';\nimport { VaultParentPermitInternal } from './VaultParentPermitInternal.sol';\nimport { VaultParentPermitLib } from './VaultParentPermitLib.sol';\nimport { IVaultParentInvestor } from './IVaultParentInvestor.sol';\nimport { VaultOwnershipInternal } from '../vault-ownership/VaultOwnershipInternal.sol';\n\nimport { IERC20 } from '@solidstate/contracts/interfaces/IERC20.sol';\nimport { SafeERC20 } from '@solidstate/contracts/utils/SafeERC20.sol';\n\n/**\n * @title   VaultParentInvestor\n * @notice  Contains logic for depositing and withdrawing from the vault\n * @dev     Apart of the VaultParent Diamond\n */\n\ncontract VaultParentInvestor is\n    VaultParentInternal,\n    VaultParentPermitInternal,\n    IVaultParentInvestor\n{\n    using SafeERC20 for IERC20;\n\n    struct DepositParams {\n        address payer;\n        address owner;\n        uint tokenId;\n        address asset;\n        uint amount;\n        uint acceptableUnitPrice;\n        address referrer;\n    }\n\n    event Deposit(\n        address depositer,\n        uint tokenId,\n        address asset,\n        uint amount,\n        uint currentUnitPrice,\n        uint shares\n    );\n\n    event WithdrawMultiChain(\n        address withdrawer,\n        uint tokenId,\n        uint portion,\n        uint currentUnitPrice,\n        uint shares\n    );\n\n    /**\n     * @notice  This modifier checks if the vault is in the process executing withdraws\n     * @dev     We don't allow total value syncs to be initiated during withdraw.\n     * @dev     Any vault value messages received after a withdraw is initiated are ignored.\n     */\n    modifier noWithdrawInProgress() {\n        require(!_withdrawInProgress(), 'withdraw in progress');\n        _;\n    }\n\n    /**\n     * @notice  This iniates a `sync` with all the child vaults\n     * @dev     The vault is considered insync once it has fresh values from all children\n     * @param   lzFees  An array of fees, one for each child chain\n     */\n    function requestTotalValueUpdateMultiChain(\n        uint[] memory lzFees\n    ) external payable noBridgeInProgress noWithdrawInProgress whenNotPaused {\n        _requestTotalValueUpdateMultiChain(lzFees);\n    }\n\n    /**\n     * @notice  Allows a deposit to be executed with a 712 Permit\n     * @dev     Anyone can relay the Permit on chain.\n     * @dev     The ERC20 Permitter and DepositPermitter must be the same\n     * @param   _depositPermit  .\n     */\n    function depositPermit(\n        DepositPermit memory _depositPermit\n    )\n        external\n        nonReentrant\n        vaultNotClosed\n        noBridgeInProgress\n        whenNotPaused\n        returns (address signer)\n    {\n        signer = _depositPermitVerifyGetSigner(_depositPermit);\n\n        _deposit(\n            DepositParams({\n                payer: signer,\n                owner: signer,\n                tokenId: _depositPermit.tokenId,\n                asset: _depositPermit.erc20Permit.token,\n                amount: _depositPermit.erc20Permit.value,\n                acceptableUnitPrice: _depositPermit.acceptableUnitPrice,\n                referrer: _depositPermit.referrer\n            })\n        );\n    }\n\n    /**\n     * @notice  Allows a withdraw to be executed with a 712 Permit\n     * @dev     Anyone can relay the Permit on chain, the owner just signs\n     * @param   _withdrawPermit  The parameters for the withdraw + signature\n     * @param   lzFees  The fees to send the withdraw request to each child chain\n     */\n    function withdrawPermit(\n        WithdrawPermit memory _withdrawPermit,\n        uint[] memory lzFees\n    )\n        external\n        payable\n        nonReentrant\n        noBridgeInProgress\n        whenNotPaused\n        returns (address signer)\n    {\n        signer = _withdrawPermitVerifyGetSigner(_withdrawPermit);\n\n        // unitPriceTrigger can be set to 0, which will skip this step\n        // And redeem the shares at the current unitPrice\n        // The vault may still need to be synced if manager needs to harvest fees\n        if (_withdrawPermit.unitPriceTrigger != 0) {\n            (uint minUnitPrice, ) = _unitPrice();\n            if (_withdrawPermit.triggerAbove) {\n                require(\n                    minUnitPrice > _withdrawPermit.unitPriceTrigger,\n                    'unitPriceTrigger: price too low'\n                );\n            } else {\n                require(\n                    minUnitPrice < _withdrawPermit.unitPriceTrigger,\n                    'unitPriceTrigger: price too high'\n                );\n            }\n        }\n\n        _withdrawMultiChain(\n            signer,\n            _withdrawPermit.tokenId,\n            _withdrawPermit.shares,\n            lzFees\n        );\n    }\n\n    /**\n     * @notice  Allows a deposit to be executed by a msg.sender for an owner\n     * @dev     DEPRECATED: Added for the DepositAutomator which is now deprecated.\n     * @dev     Note: msg.sender is the payer, owner is the owner of the holding\n     * @dev     Note: See modifiers for restrictions\n     * @param   owner    The owner of the holding or to be owner\n     * @param   tokenId  The tokenId of the holding\n     * @param   asset  The asset to deposit\n     * @param   amount  The amount to deposit\n     */\n    function depositFor(\n        address owner,\n        uint tokenId,\n        address asset,\n        uint amount,\n        uint acceptableUnitPrice,\n        address referrer\n    ) external vaultNotClosed noBridgeInProgress whenNotPaused nonReentrant {\n        require(\n            msg.sender == _registry().depositAutomator(),\n            'only DepositAutomator'\n        );\n        _deposit(\n            DepositParams({\n                payer: msg.sender,\n                owner: owner,\n                tokenId: tokenId,\n                asset: asset,\n                amount: amount,\n                acceptableUnitPrice: acceptableUnitPrice,\n                referrer: referrer\n            })\n        );\n    }\n\n    /**\n     * @notice  Allows a msg.sender to deposit into a holding\n     * @dev     Vault must be `in sync` before calling\n     * @dev     Note: See modifiers for restrictions\n     * @dev     Note: msg.sender is the payer and owner of the holding\n     * @param   tokenId  The tokenId of the holding\n     * @param   asset  The asset to deposit\n     * @param   amount  The amount to deposit\n     * @param   acceptableUnitPrice  The acceptable unit price to pay for shares\n     * @param   referrer  The referrer (optional)\n     */\n    function deposit2(\n        uint tokenId,\n        address asset,\n        uint amount,\n        uint acceptableUnitPrice,\n        address referrer\n    ) external vaultNotClosed noBridgeInProgress whenNotPaused nonReentrant {\n        _deposit(\n            DepositParams({\n                payer: msg.sender,\n                owner: msg.sender,\n                tokenId: tokenId,\n                asset: asset,\n                amount: amount,\n                acceptableUnitPrice: acceptableUnitPrice,\n                referrer: referrer\n            })\n        );\n    }\n\n    /**\n     * @notice  Allows a msg.sender to deposit into a holding\n     * @dev     DEPRECATED used deposit2 instead, will be replaced with deposit2\n     * @dev     Vault must be `in sync` before calling\n     * @dev     Note: See modifiers for restrictions\n     * @dev     Note: msg.sender is the payer and owner of the holding\n     * @param   tokenId  The tokenId of the holding\n     * @param   asset  The asset to deposit\n     * @param   amount  The amount to deposit\n     */\n    function deposit(\n        uint tokenId,\n        address asset,\n        uint amount\n    ) external vaultNotClosed noBridgeInProgress whenNotPaused nonReentrant {\n        _deposit(\n            DepositParams({\n                payer: msg.sender,\n                owner: msg.sender,\n                tokenId: tokenId,\n                asset: asset,\n                amount: amount,\n                acceptableUnitPrice: type(uint).max,\n                referrer: address(0)\n            })\n        );\n    }\n\n    /**\n     * @notice  Allows a msg.sender to withdraw from a holding\n     * @dev     msg.sender must be owner of the holding\n     * @param   tokenId  The tokenId of the holding\n     * @param   amount  The amount of shares to withdraw and burn\n     * @param   lzFees  The fees to send the withdraw request to each child chain\n     */\n    function withdrawMultiChain(\n        uint tokenId,\n        uint amount,\n        uint[] memory lzFees\n    ) external payable noBridgeInProgress whenNotPaused nonReentrant {\n        _withdrawMultiChain(msg.sender, tokenId, amount, lzFees);\n    }\n\n    ///\n    /// Internal\n    ///\n\n    /**\n     * @notice  Deposits an asset into the vault\n     * @dev     The vault must be insync if it has active children\n     * @param   depositParams  The parameters for the deposit\n     */\n    function _deposit(DepositParams memory depositParams) internal {\n        require(\n            _registry().depositAssets(depositParams.asset),\n            'not deposit asset'\n        );\n\n        /// Hack for now to limit each user to 1 holding\n        /// Accept the manager, they can have fee holding + another holding\n        /// transferring of tokens is currently disabled\n        if (depositParams.tokenId == 0) {\n            uint numHoldings = _balanceOf(depositParams.owner);\n            if (depositParams.owner == _manager()) {\n                require(numHoldings < 2, 'manager already owns holdings');\n            } else {\n                require(numHoldings < 1, 'already owns holding');\n            }\n        }\n\n        /// Vaults that have hard deprecated assets cannot be valued accurately\n        /// Therefore deposits are blocked until the manager trades out of the asset\n        (\n            ,\n            uint maxVaultValue,\n            bool hasHardDeprecatedAsset\n        ) = _totalValueAcrossAllChains();\n\n        require(!hasHardDeprecatedAsset, 'holds hard deprecated asset');\n\n        uint totalShares = _totalShares();\n\n        if (totalShares > 0 && maxVaultValue == 0) {\n            // This means all the shares issue are currently worthless\n            // We can't issue anymore shares\n            revert('vault closed');\n        }\n        (uint depositValueInUSD, ) = _registry().accountant().assetValue(\n            depositParams.asset,\n            depositParams.amount\n        );\n\n        uint customCapForVault = _registry().customVaultValueCap(address(this));\n\n        if (customCapForVault > 0) {\n            require(\n                maxVaultValue + depositValueInUSD <= customCapForVault,\n                'vault will exceed custom cap'\n            );\n        } else {\n            require(\n                maxVaultValue + depositValueInUSD <=\n                    _registry().vaultValueCap(),\n                'vault will exceed cap'\n            );\n        }\n\n        // if tokenId == 0 means were creating a new holding\n        if (depositParams.tokenId == 0) {\n            require(\n                depositValueInUSD >= _registry().minDepositAmount(),\n                'min deposit not met'\n            );\n        }\n\n        // Note: that we are taking the deposit asset from the payer\n        IERC20(depositParams.asset).safeTransferFrom(\n            depositParams.payer,\n            address(this),\n            depositParams.amount\n        );\n        _updateActiveAsset(depositParams.asset);\n\n        uint shares;\n        uint currentUnitPrice;\n        if (totalShares == 0) {\n            shares = depositValueInUSD;\n            // We should debate if the base unit of the vaults is to be 10**18 or 10**8.\n            // 10**8 is the natural unit for USD (which is what the unitPrice is denominated in),\n            // but 10**18 gives us more precision when it comes to leveling fees.\n            currentUnitPrice = _unitPrice(depositValueInUSD, shares);\n        } else {\n            shares = (depositValueInUSD * totalShares) / maxVaultValue;\n            // Don't used unitPrice() because it will encorporate the deposited funds, but shares haven't been issue yet\n            currentUnitPrice = _unitPrice(maxVaultValue, totalShares);\n        }\n\n        require(\n            currentUnitPrice <= depositParams.acceptableUnitPrice,\n            'unit price too high'\n        );\n\n        uint issuedToTokenId = _issueShares(\n            depositParams.tokenId,\n            depositParams.owner,\n            shares,\n            currentUnitPrice,\n            _registry().depositLockupTime(),\n            _registry().protocolFeeBips(),\n            depositParams.referrer\n        );\n\n        uint holdingTotalShares = _holdings(issuedToTokenId).totalShares;\n        uint holdingTotalValue = (currentUnitPrice * holdingTotalShares) /\n            Constants.VAULT_PRECISION;\n\n        // If the vault has a custom cap\n        // there is not holding maxDepositAmount\n        require(\n            customCapForVault > 0 ||\n                holdingTotalValue <= _registry().maxDepositAmount(),\n            'exceeds max deposit'\n        );\n\n        emit Deposit(\n            depositParams.owner,\n            issuedToTokenId,\n            depositParams.asset,\n            depositParams.amount,\n            currentUnitPrice,\n            shares\n        );\n        _registry().emitEvent();\n    }\n\n    /**\n     * @notice  Burns shares and redeems assets\n     * @dev     Note: the holding owner always receives the assets\n     * @dev     If the vault has active children and the manager has performance fees enabled\n     * @dev     The vault must be insync\n     * @param   _msgSender The msg.sender or permitter\n     * @param   tokenId    The tokenId of the holding\n     * @param   amount     The amount of shares to burn\n     * @param   lzFees     The fees to send the withdraw request to each child chain\n     */\n    function _withdrawMultiChain(\n        address _msgSender,\n        uint tokenId,\n        uint amount,\n        uint[] memory lzFees\n    ) internal {\n        // Withdraws are always redeemed to the owner\n        address owner = _ownerOf(tokenId);\n        require(\n            _msgSender == owner ||\n                _msgSender == _registry().withdrawAutomator(),\n            'not allowed'\n        );\n\n        uint minUnitPrice = _getFeeLevyUnitPrice(tokenId);\n        _levyFees(tokenId, minUnitPrice, _registry().protocolFeeBips());\n\n        uint sharesRemainingAfterFeeLevy = _holdings(tokenId).totalShares;\n\n        // If the shares remaining after the fee levy is less than the amount\n        // the user wants to withdraw, we will just withdraw all the remaining shares\n        if (sharesRemainingAfterFeeLevy < amount) {\n            amount = sharesRemainingAfterFeeLevy;\n        }\n\n        uint portion = (amount * Constants.PORTION_DIVISOR) / _totalShares();\n        _burnShares(tokenId, amount);\n        _withdraw(tokenId, owner, portion);\n        _adjustCachedChainTotalValues(portion);\n        _sendWithdrawRequestsToChildrenMultiChain(\n            tokenId,\n            owner,\n            portion,\n            lzFees\n        );\n\n        emit WithdrawMultiChain(owner, tokenId, portion, minUnitPrice, amount);\n        _registry().emitEvent();\n    }\n\n    /**\n     * @notice  Adjusts the cached chain total values for all the child vaults down proportionally\n     * @dev     This is called during withdraw. So that other withdraws/deposits can be executed for a single sync\n     * @param   withdrawnPortion  The portion of shares that were withdrawn\n     */\n    function _adjustCachedChainTotalValues(uint withdrawnPortion) internal {\n        // We want to allow multiple withdraws to be processed at once.\n        // So they can share the same `sync` and not block deposits during withdraw.\n        // Because we are burning shares, during withdraw\n        // We must adjust the cached values for all the child vaults proportionally\n        // Otherwise the unitPrice will be incorrect\n        // We block requestTotalValueUpdateMultiChain & receiveChildValue until all withdraws are 100% complete.\n        // This was added after the fact and probably could have been achieved in a better way\n        VaultParentStorage.Layout storage l = VaultParentStorage.layout();\n\n        for (uint8 i = 0; i < l.childChains.length; i++) {\n            if (_childIsInactive(l.childChains[i])) {\n                continue;\n            }\n\n            l.chainTotalValues[l.childChains[i]].minValue -=\n                (l.chainTotalValues[l.childChains[i]].minValue *\n                    withdrawnPortion) /\n                Constants.PORTION_DIVISOR;\n            l.chainTotalValues[l.childChains[i]].maxValue -=\n                (l.chainTotalValues[l.childChains[i]].maxValue *\n                    withdrawnPortion) /\n                Constants.PORTION_DIVISOR;\n        }\n    }\n\n    ///\n    /// Cross Chain Requests\n    ///\n\n    /**\n     * @notice  Sends a totalValueUpdateRequest to all the active child vaults\n     * @dev     This will force the child vault to send back a vaultValue update\n     * @param   lzFees  An array of fees, one for each child chain\n     */\n    function _requestTotalValueUpdateMultiChain(uint[] memory lzFees) internal {\n        VaultParentStorage.Layout storage l = VaultParentStorage.layout();\n\n        uint totalFees;\n\n        for (uint8 i = 0; i < l.childChains.length; i++) {\n            if (_childIsInactive(l.childChains[i])) {\n                require(lzFees[i] == 0, 'no fee required');\n                continue;\n            }\n            totalFees += lzFees[i];\n            uint16 childChainId = l.childChains[i];\n\n            _registry().transport().sendValueUpdateRequest{ value: lzFees[i] }(\n                ITransport.ValueUpdateRequest({\n                    parentChainId: _registry().chainId(),\n                    parentVault: address(this),\n                    child: ITransport.ChildVault({\n                        vault: l.children[childChainId],\n                        chainId: childChainId\n                    })\n                })\n            );\n        }\n\n        require(msg.value >= totalFees, 'insufficient fee sent');\n    }\n\n    /**\n     * @notice  This sends the withdraw requests to all the active child vaults\n     * @dev     This will force the child to redeem the assets it holds to the withdrawer\n     * @dev     This will force the child vault to send back a withdraw complete update\n     * @param   tokenId  The tokenId of the holding (only used for offchain tracking)\n     * @param   withdrawer  The address to redeem the assets to\n     * @param   portion  The portion of the vault to redeem\n     * @param   lzFees  The fees to send the withdraw request to each child chain\n     */\n    function _sendWithdrawRequestsToChildrenMultiChain(\n        uint tokenId,\n        address withdrawer,\n        uint portion,\n        uint[] memory lzFees\n    ) internal {\n        VaultParentStorage.Layout storage l = VaultParentStorage.layout();\n        uint totalFees;\n        for (uint8 i = 0; i < l.childChains.length; i++) {\n            if (_childIsInactive(l.childChains[i])) {\n                require(lzFees[i] == 0, 'no fee required');\n                continue;\n            }\n            totalFees += lzFees[i];\n            _sendWithdrawRequest(\n                l.childChains[i],\n                tokenId,\n                withdrawer,\n                portion,\n                lzFees[i]\n            );\n        }\n        require(msg.value >= totalFees, 'insufficient fee');\n    }\n\n    /**\n     * @notice  Sends a withdraw request to a child vault\n     * @dev     This will force the child to redeem the assets it holds to the withdrawer\n     * @dev     This will force the child vault to send back a withdraw complete update\n     * @param   dstChainId  The chainId of the destination\n     * @param   tokenId  The tokenId of the holding (only used for offchain tracking)\n     * @param   withdrawer  The address to redeem the assets to\n     * @param   portion  The portion of the vault to redeem\n     * @param   sendFee  The lz fee to send the withdraw request to the child chain\n     */\n    function _sendWithdrawRequest(\n        uint16 dstChainId,\n        uint tokenId,\n        address withdrawer,\n        uint portion,\n        uint sendFee\n    ) internal {\n        VaultParentStorage.Layout storage l = VaultParentStorage.layout();\n        l.withdrawsInProgress++;\n        _registry().transport().sendWithdrawRequest{ value: sendFee }(\n            ITransport.WithdrawRequest({\n                parentChainId: _registry().chainId(),\n                parentVault: address(this),\n                child: ITransport.ChildVault({\n                    chainId: dstChainId,\n                    vault: l.children[dstChainId]\n                }),\n                tokenId: tokenId,\n                withdrawer: withdrawer,\n                portion: portion\n            })\n        );\n    }\n\n    /**\n     * @notice  Returns the unit price of the vault used to calculate fees\n     * @dev     If the vault is not in sync, this will revert\n     * @dev     If the Manager is not charging a performance fees we do not need the unitPrice\n     * @dev     If tokenId is precluded from paying fees we do not need the unitPrice\n     * @param   tokenId  The tokenId of the holding\n     * @return  uint  The unit price of the vault\n     */\n    function _getFeeLevyUnitPrice(uint tokenId) internal view returns (uint) {\n        // If a Manager is not charging a performance fee we do not need the currentUnitPrice\n        // to process a withdraw, because all withdraws are porpotional.\n        // In addition if the tokendId is System Token (manager, protocol). We don't levy fees on these tokens.\n        // I don't really like smuggling this logic in here at this level\n        // But it means that if a manager isn't charging a performanceFee then we don't have to impose a totalValueSync\n        uint minUnitPrice;\n        if (!_inSync() && !_requiresUnitPrice(tokenId)) {\n            minUnitPrice = 0;\n        } else {\n            // This will revert if the vault is not in sync\n            // We are discarding hasHardDeprecatedAsset because we don't want to block withdraws\n            (minUnitPrice, ) = _unitPrice();\n        }\n\n        return minUnitPrice;\n    }\n\n    /**\n     * @notice  Returns the vault name used for eip712\n     * @return  string the name of the vault\n     */\n    function _name()\n        internal\n        view\n        virtual\n        override(VaultParentPermitInternal, VaultOwnershipInternal)\n        returns (string memory)\n    {\n        return VaultOwnershipInternal._name();\n    }\n}\n"
      },
      "contracts/vault-parent/VaultParentManager.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nimport { ITransport } from '../transport/ITransport.sol';\nimport { IStargateRouter } from '@layerzerolabs/solidity-examples/contracts/interfaces/IStargateRouter.sol';\nimport { VaultParentStorage } from './VaultParentStorage.sol';\nimport { VaultParentInternal } from './VaultParentInternal.sol';\nimport { IVaultParentManager } from './IVaultParentManager.sol';\nimport { Constants } from '../lib/Constants.sol';\nimport { VaultOwnershipStorage } from '../vault-ownership/VaultOwnershipStorage.sol';\n\nimport { IERC20 } from '@solidstate/contracts/interfaces/IERC20.sol';\nimport { SafeERC20 } from '@solidstate/contracts/utils/SafeERC20.sol';\n\ncontract VaultParentManager is VaultParentInternal, IVaultParentManager {\n    using SafeERC20 for IERC20;\n\n    uint public constant CLOSE_FEE = 0.027 ether;\n\n    event FundClosed();\n\n    /**\n     * @notice  Allows a manager to close their vault\n     * @dev     Once closed a vault cannot be deposited into, withdraws can still be made\n     * @dev     Cannot be reopened\n     */\n    function closeVault()\n        external\n        payable\n        vaultNotClosed\n        onlyManager\n        whenNotPaused\n    {\n        require(msg.value >= CLOSE_FEE, 'insufficient fee');\n        (bool sent, ) = _registry().protocolTreasury().call{ value: msg.value }(\n            ''\n        );\n        require(sent, 'Failed to process close fee');\n        VaultParentStorage.Layout storage l = VaultParentStorage.layout();\n\n        l.vaultClosed = true;\n        _registry().emitEvent();\n        emit FundClosed();\n    }\n\n    /**\n     * @notice  Allows manager to set a manager fee discount on a holding\n     * @dev     Denominated in basis points 10000 = 100%\n     * @param   tokenId  the tokenId of the holding\n     * @param   streamingFeeDiscount the discount to apply to the streaming fee\n     * @param   performanceFeeDiscount  the discount to apply to the performance fee\n     */\n    function setDiscountForHolding(\n        uint tokenId,\n        uint streamingFeeDiscount,\n        uint performanceFeeDiscount\n    ) external onlyManager whenNotPaused {\n        _setDiscountForHolding(\n            tokenId,\n            streamingFeeDiscount,\n            performanceFeeDiscount\n        );\n    }\n\n    /**\n     * @notice  Levies both the streaming and performance fees on a holding\n     * @dev     At the moment this function is only callable by the manager\n     * @dev     The caller should make sure that each tokenId can harvest fees before calling\n     * @dev     This could be revised\n     * @param   tokenIds  the tokenIds of the holdings to levy fees on\n     */\n    function levyFeesOnHoldings(\n        uint[] memory tokenIds\n    ) external onlyManager whenNotPaused {\n        uint minUnitPrice;\n        bool isInSync = _inSync();\n        if (isInSync) {\n            (minUnitPrice, ) = _unitPrice();\n        }\n\n        for (uint i = 0; i < tokenIds.length; i++) {\n            require(\n                block.timestamp >=\n                    _holdings(tokenIds[i]).lastManagerFeeLevyTime + 24 hours,\n                'already levied this period'\n            );\n            // If the manager has performance fees enabled and its a multichain\n            // vault we must sync the vault before levying fees so we have the correct unitPrice\n            if (!isInSync && _requiresSyncForFees(tokenIds[i])) {\n                revert('vault not in sync');\n            }\n            _levyFees(tokenIds[i], minUnitPrice, _registry().protocolFeeBips());\n        }\n        _registry().emitEvent();\n    }\n\n    /// Fees\n\n    /**\n     * @notice  Sets the current referrer share\n     * @dev     Denominated in basis points 10000 = 100%\n     * @dev     Any existing referrers will keep their exsiting share\n     * @param   newReferrerShareBips  .\n     */\n    function setReferrerShareBips(\n        uint newReferrerShareBips\n    ) external onlyManager whenNotPaused {\n        _setReferrerShareBips(newReferrerShareBips);\n        _registry().emitEvent();\n    }\n\n    /**\n     * @notice  Allows the manager to annouce a streaming fee or performance fee increase\n     * @dev     They must wait the _FEE_ANNOUNCE_WINDOW before commiting the change\n     * @param   newStreamingFee  The streaming fee in basis points\n     * @param   newPerformanceFee  The performance fee in basis points\n     */\n    function announceFeeIncrease(\n        uint256 newStreamingFee,\n        uint256 newPerformanceFee\n    ) external onlyManager whenNotPaused {\n        require(_registry().canChangeManagerFees(), 'fee change disabled');\n        _announceFeeIncrease(newStreamingFee, newPerformanceFee);\n        _registry().emitEvent();\n    }\n\n    /**\n     * @notice  Commits the fee increase previously announced\n     * @dev     Can only be called after _FEE_ANNOUNCE_WINDOW has passed\n     */\n    function commitFeeIncrease() external onlyManager whenNotPaused {\n        _commitFeeIncrease();\n        _registry().emitEvent();\n    }\n\n    /**\n     * @notice  Allows the manager to renounce a fee increase\n     * @dev     Can be called at anytime\n     */\n    function renounceFeeIncrease() external onlyManager whenNotPaused {\n        _renounceFeeIncrease();\n        _registry().emitEvent();\n    }\n\n    // Manager Actions\n\n    /**\n     * @notice  Allows the manager to send a bridge approval to a child vault\n     * @dev     A childVault cannot bridge unless approved by the parent vault\n     * @dev     This is to avoid the case where funds are inflight during a sync or withdraw\n     * @dev     The parent vault is locked (no deposits, no withdraws) while there is an outstanding bridge approval\n     * @dev     The manager must initate a bridge from the child or cancel the bridge approval from the child\n     * @dev     This is not ideal and we are working on a better solution\n     * @param   dstChainId  The lzChainId of the child vault\n     */\n    function sendBridgeApproval(\n        uint16 dstChainId,\n        uint // unused kept for compatibility\n    )\n        external\n        payable\n        nonReentrant\n        onlyManager\n        noBridgeInProgress\n        whenNotPaused\n    {\n        VaultParentStorage.Layout storage l = VaultParentStorage.layout();\n        // If the bridge approval is cancelled the manager is block from initiating another for 1 hour\n        // This protects users from being ddos'd and not being able to withdraw\n        // because the manager keeps applying a bridge lock\n        require(\n            l.lastBridgeCancellation + 1 hours < block.timestamp,\n            'bridge approval timeout'\n        );\n        address dstVault = l.children[dstChainId];\n        require(dstVault != address(0), 'no dst vault');\n        l.bridgeInProgress = true;\n        l.bridgeApprovedFor = dstChainId;\n\n        _registry().transport().sendBridgeApproval{ value: msg.value }(\n            ITransport.BridgeApprovalRequest({\n                approvedChainId: dstChainId,\n                approvedVault: dstVault\n            })\n        );\n    }\n\n    /**\n     * @notice  Allows the manager to bridge an asset from the parent vault to a child vault\n     * @dev     Currently via stargate via the transport layer\n     * @dev     Note: the vault is locked until the child receives and acknowledges the bridge\n     * @param   dstChainId  The lzChainId of the child vault\n     * @param   asset  The address of the asset to bridge\n     * @param   amount  The amount of the asset to bridge\n     * @param   minAmountOut  The minimum amount of the asset to receive on the child chain\n     */\n    function requestBridgeToChain(\n        uint16 dstChainId,\n        address asset,\n        uint amount,\n        uint minAmountOut,\n        uint // unused kept for compatibility\n    )\n        external\n        payable\n        nonReentrant\n        onlyManager\n        noBridgeInProgress\n        whenNotPaused\n    {\n        VaultParentStorage.Layout storage l = VaultParentStorage.layout();\n\n        address dstVault = l.children[dstChainId];\n        require(dstVault != address(0), 'no dst vault');\n        l.bridgeInProgress = true;\n        // Once the manager has bridged we must include the childChains in our total value\n        l.childIsInactive[dstChainId] = false;\n        _bridgeAsset(\n            dstChainId,\n            dstVault,\n            _registry().chainId(),\n            address(this),\n            asset,\n            amount,\n            minAmountOut,\n            msg.value\n        );\n    }\n\n    /**\n     * @notice  Allows the manager to create a child vault\n     * @dev     1 child vault per chain only\n     * @dev     Can only create 1 child at a time, locked until the child acknowledges the creation\n     * @param   newChainId  The lzChainId of the child vault\n     */\n    function requestCreateChild(\n        uint16 newChainId,\n        uint // unsused kept for compatibility\n    ) external payable nonReentrant onlyManager whenNotPaused {\n        VaultParentStorage.Layout storage l = VaultParentStorage.layout();\n\n        require(!l.childCreationInProgress, 'sibling creation inprogress');\n        require(l.children[newChainId] == address(0), 'sibling exists');\n        require(newChainId != _registry().chainId(), 'not same chain');\n        l.childCreationInProgress = true;\n        ITransport.ChildVault[]\n            memory existingChildren = new ITransport.ChildVault[](\n                l.childChains.length\n            );\n\n        for (uint8 i = 0; i < l.childChains.length; i++) {\n            existingChildren[i].chainId = l.childChains[i];\n            existingChildren[i].vault = l.children[l.childChains[i]];\n        }\n        _registry().transport().sendVaultChildCreationRequest{\n            value: msg.value\n        }(\n            ITransport.VaultChildCreationRequest({\n                parentVault: address(this),\n                parentChainId: _registry().chainId(),\n                newChainId: newChainId,\n                manager: _manager(),\n                riskProfile: _riskProfile(),\n                children: existingChildren\n            })\n        );\n    }\n\n    /**\n     * @notice  Changes the manager of the parent vault and all children\n     * @param   newManager  The address of the new manager\n     * @param   lzFees  The fees to send the update message to each child\n     */\n    function changeManagerMultiChain(\n        address newManager,\n        uint[] memory lzFees\n    ) external payable nonReentrant onlyManager whenNotPaused {\n        require(_registry().canChangeManager(), 'manager change disabled');\n        require(newManager != address(0), 'invalid newManager');\n        address oldManager = _manager();\n        _changeManager(newManager);\n        _transfer(oldManager, newManager, _MANAGER_TOKEN_ID);\n        _sendChangeManagerRequestToChildren(newManager, lzFees);\n    }\n\n    /**\n     * @notice  Returns true if the parent has anonymous active child vaults\n     * @return  bool  True if the parent has active children\n     */\n    function hasActiveChildren() external view returns (bool) {\n        return _hasActiveChildren();\n    }\n\n    /**\n     * @notice  Returns the total number of all outstanding shares\n     * @return  uint  The total number of all outstanding shares\n     */\n    function totalShares() external view returns (uint) {\n        return _totalShares();\n    }\n\n    /**\n     * @notice  Returns the min and max unitprice for a vault\n     * @dev     Will revert if vault is not insync\n     * @return  minPrice  The min unit price\n     * @return  maxPrice  The max unit price\n     */\n    function unitPrice() external view returns (uint minPrice, uint maxPrice) {\n        return _unitPrice();\n    }\n\n    /**\n     * @notice  Returns a holding by tokenId\n     * @param   tokenId  the tokenId of the holding\n     * @return  VaultOwnershipStorage.Holding  The holding struct\n     */\n    function holdings(\n        uint tokenId\n    ) external view returns (VaultOwnershipStorage.Holding memory) {\n        return _holdings(tokenId);\n    }\n\n    /**\n     * @notice  Returns if a bridge is in progress\n     * @dev     Frontend helper\n     * @return  bool  True if a bridge is in progress\n     */\n    function bridgeInProgress() external view returns (bool) {\n        return _bridgeInProgress();\n    }\n\n    /**\n     * @notice  Returns the lzChainId if there is a outstanding bridge approval\n     * @dev     Returns 0 if there is no outstanding bridge approval\n     * @return  uint16  the lzChainId or 0\n     */\n    function bridgeApprovedFor() external view returns (uint16) {\n        return _bridgeApprovedFor();\n    }\n\n    /**\n     * @notice  Calculates the unpaid fees for a holding based on the given unit price\n     * @dev     The currentMinUnitPrice can be calculated offChain and used\n     * @dev     Used to display owed fees in the frontend\n     * @param   tokenId  The tokenId of the holding\n     * @param   currentMinUnitPrice  the current minUnitPrice of the vault\n     * @return  streamingFees  owed streaming fees denominated in shares\n     * @return  performanceFees  owed performance fees denominated in shares\n     */\n    function calculateUnpaidFees(\n        uint tokenId,\n        uint currentMinUnitPrice\n    ) external view returns (uint streamingFees, uint performanceFees) {\n        return _calculateUnpaidFees(tokenId, currentMinUnitPrice);\n    }\n\n    /**\n     * @notice  Returns if the vault is closed\n     * @dev     Helper for frontend\n     * @return  bool  True if the vault is closed\n     */\n    function vaultClosed() external view returns (bool) {\n        return _vaultClosed();\n    }\n\n    /**\n     * @notice  Returns if the tokenId requires a sync for harvesting fees\n     * @dev     Helper for the frontend to calculated tokenIds for levyFeesOnHoldings\n     * @param   tokenId  the tokenId of the holding\n     * @return  bool  True if the tokenId requires a sync for harvesting fees\n     */\n    function requiresSyncForFees(uint tokenId) external view returns (bool) {\n        return _requiresSyncForFees(tokenId);\n    }\n\n    /// Fees\n\n    /**\n     * @notice  Returns the holdings referrer information\n     * @dev     The struct can be empty\n     * @param   tokenId  the tokenId of the holding\n     * @return  VaultOwnershipStorage.HoldingReferrer  The holding referrer struct\n     */\n    function holdingReferrer(\n        uint tokenId\n    ) external view returns (VaultOwnershipStorage.HoldingReferrer memory) {\n        return _holdingReferrer(tokenId);\n    }\n\n    /**\n     * @notice  Returns the current referrer share\n     * @dev     Denominated in basis points 10000 = 100%\n     * @return  uint  The current referrer share\n     */\n    function referrerShareBips() external view returns (uint) {\n        return _referrerShareBips();\n    }\n\n    /**\n     * @notice  Returns the current performance fee\n     * @dev     Denominated in basis points 10000 = 100%\n     * @return  uint  The current performance fee\n     */\n    function managerPerformanceFee() external view returns (uint) {\n        return _managerPerformanceFee();\n    }\n\n    /**\n     * @notice  Returns the current streaming fee\n     * @dev     Denominated in basis points 10000 = 100%\n     * @return  uint  The current streaming fee\n     */\n    function managerStreamingFee() external view returns (uint) {\n        return _managerStreamingFee();\n    }\n\n    /**\n     * @notice  Returns the announced manager performance fee\n     * @dev     Denominated in basis points 10000 = 100%\n     * @dev     Returns 0 if there is no announced fee increase\n     * @return  uint  The announced manager performance fee\n     */\n    function announcedManagerPerformanceFee() external view returns (uint) {\n        return _announcedManagerPerformanceFee();\n    }\n\n    /**\n     * @notice  Returns the announced manager streaming fee\n     * @dev     Denominated in basis points 10000 = 100%\n     * @dev     Returns 0 if there is no announced fee increase\n     * @return  uint  The announced manager streaming fee\n     */\n    function announcedManagerStreamingFee() external view returns (uint) {\n        return _announcedManagerStreamingFee();\n    }\n\n    /**\n     * @notice  Returns the timestamp of the announced fee increase\n     * @dev     This is when the fee increase was announced\n     * @dev     0 if there is not annonced fee increase\n     * @return  uint  The timestamp of the announced fee increase\n     */\n    function announcedFeeIncreaseTimestamp() external view returns (uint) {\n        return _announcedFeeIncreaseTimestamp();\n    }\n\n    /**\n     * @notice  Returns the protocols share of the given fees\n     * @param   managerFees  The total fees\n     * @return  uint  The protocols share of the given fees\n     */\n    function protocolFee(uint managerFees) external view returns (uint) {\n        return _protocolFee(managerFees, _registry().protocolFeeBips());\n    }\n\n    /**\n     * @notice  Returns the vaults unit precision\n     * @return  uint  The vaults unit precision\n     */\n    function VAULT_PRECISION() external pure returns (uint) {\n        return Constants.VAULT_PRECISION;\n    }\n\n    /**\n     * @notice  Returns the performance fees owed given the parameters\n     * @dev     Helper for the frontend\n     * @param   fee  The performance fee in basis points\n     * @param   discount  The discount in basis points\n     * @param   __totalShares  The total shares\n     * @param   tokenPriceStart  The token price at the start\n     * @param   tokenPriceFinish  The token price at the finish\n     * @return  sharesOwed  the performance fees owed to the manager in shares\n     */\n    function performanceFee(\n        uint fee,\n        uint discount,\n        uint __totalShares,\n        uint tokenPriceStart,\n        uint tokenPriceFinish\n    ) external pure returns (uint sharesOwed) {\n        return\n            _performanceFee(\n                fee,\n                discount,\n                __totalShares,\n                tokenPriceStart,\n                tokenPriceFinish\n            );\n    }\n\n    /**\n     * @notice  Returns the streaming fees owed given the parameters\n     * @dev     Helper for the frontend\n     * @param   fee  The streaming fee in basis points\n     * @param   discount  The discount in basis points\n     * @param   lastFeeTime  The last time the fee was levied\n     * @param   __totalShares  The total shares\n     * @param   timeNow  The current time\n     * @return  sharesOwed  the streaming fees owed to the manager in shares\n     */\n    function streamingFee(\n        uint fee,\n        uint discount,\n        uint lastFeeTime,\n        uint __totalShares,\n        uint timeNow\n    ) external pure returns (uint sharesOwed) {\n        return\n            _streamingFee(fee, discount, lastFeeTime, __totalShares, timeNow);\n    }\n\n    /**\n     * @notice  Returns the current fee announce window\n     * @dev     The amount of time that needs to pass before a fee change can be commited\n     * @return  uint  The current fee announce window\n     */\n    function FEE_ANNOUNCE_WINDOW() external pure returns (uint) {\n        return _FEE_ANNOUNCE_WINDOW;\n    }\n\n    /**\n     * @notice  Returns the maximum streaming fee that can be set by the manager\n     * @dev     Denominated in basis points 10000 = 100%\n     * @return  uint  The maximum streaming fee that can be set by the manager\n     */\n    function MAX_STREAMING_FEE_BASIS_POINTS() external pure returns (uint) {\n        return _MAX_STREAMING_FEE_BASIS_POINTS;\n    }\n\n    /**\n     * @notice  Returns the maximum single step change in the streaming fee that can be made by a manager\n     * @dev     Denominated in basis points 10000 = 100%\n     * @dev     Manager cannot just immediately go from 0% to 5%\n     * @return  uint  The maximum single step change in the streaming fee that can be made by a manager\n     */\n    function MAX_STREAMING_FEE_BASIS_POINTS_STEP()\n        external\n        pure\n        returns (uint)\n    {\n        return _MAX_STREAMING_FEE_BASIS_POINTS_STEP;\n    }\n\n    /**\n     * @notice  Returns the maximum performance fee that can be set by the manager\n     * @dev     Denominated in basis points 10000 = 100%\n     * @return  uint  The maximum performance fee that can be set by the manager\n     */\n    function MAX_PERFORMANCE_FEE_BASIS_POINTS() external pure returns (uint) {\n        return _MAX_PERFORMANCE_FEE_BASIS_POINTS;\n    }\n\n    /**\n     * @notice  Returns the duration of the streaming fee period\n     * @dev     Currently 365 days, 1% streaming fee is delivered 1/365th per day\n     * @return  uint  The duration of the streaming fee period\n     */\n    function STEAMING_FEE_DURATION() external pure returns (uint) {\n        return _STEAMING_FEE_DURATION;\n    }\n\n    /**\n     * @notice  The tokenId of the manager holding\n     * @dev     The manager holding is create on vault creation\n     * @return  uint  The tokenId of the manager holding\n     */\n    function MANAGER_TOKEN_ID() external pure returns (uint) {\n        return _MANAGER_TOKEN_ID;\n    }\n\n    /**\n     * @notice  The tokenId of the protocol holding\n     * @dev     The protocol holding is create on vault creation\n     * @return  uint  The tokenId of the protocol holding\n     */\n    function PROTOCOL_TOKEN_ID() external pure returns (uint) {\n        return _PROTOCOL_TOKEN_ID;\n    }\n\n    /**\n     * @notice  Returns the maximum single step change in the performance fee that can be made by a manager\n     * @dev     Denominated in basis points 10000 = 100%\n     * @dev     Manager cannot just immediately go from 0% to 50%\n     * @return  uint  The maximum single step change in the performance fee that can be made by a manager\n     */\n    function MAX_PERFORMANCE_FEE_BASIS_POINTS_STEP()\n        external\n        pure\n        returns (uint)\n    {\n        return _MAX_PERFORMANCE_FEE_BASIS_POINTS_STEP;\n    }\n\n    /// Internals\n\n    /**\n     * @notice  Changes the manager of the parent vault and all children\n     * @param   newManager  The address of the new manager\n     * @param   lzFees The fees to send the update message to each child\n     */\n    function _sendChangeManagerRequestToChildren(\n        address newManager,\n        uint[] memory lzFees\n    ) internal {\n        VaultParentStorage.Layout storage l = VaultParentStorage.layout();\n        uint totalFees;\n        for (uint8 i = 0; i < l.childChains.length; i++) {\n            totalFees += lzFees[i];\n            _sendChangeManagerRequest(l.childChains[i], newManager, lzFees[i]);\n        }\n        require(msg.value >= totalFees, 'insufficient fee');\n    }\n\n    /**\n     * @notice  Sends a change manager request to a child vault\n     * @param   dstChainId  The lzChainId of the child vault\n     * @param   newManager  The address of the new manager\n     * @param   sendFee  the lzFee to send the change mesage\n     */\n    function _sendChangeManagerRequest(\n        uint16 dstChainId,\n        address newManager,\n        uint sendFee\n    ) internal {\n        VaultParentStorage.Layout storage l = VaultParentStorage.layout();\n\n        _registry().transport().sendChangeManagerRequest{ value: sendFee }(\n            ITransport.ChangeManagerRequest({\n                child: ITransport.ChildVault({\n                    chainId: dstChainId,\n                    vault: l.children[dstChainId]\n                }),\n                newManager: newManager\n            })\n        );\n    }\n}\n"
      },
      "contracts/vault-parent/VaultParentPermitInternal.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nimport { IERC2612 } from '@solidstate/contracts/token/ERC20/permit/IERC2612.sol';\nimport { IERC20 } from '@solidstate/contracts/interfaces/IERC20.sol';\nimport { IERC20Metadata } from '@solidstate/contracts/token/ERC20/metadata/IERC20Metadata.sol';\nimport { ECDSA } from '@solidstate/contracts/cryptography/ECDSA.sol';\nimport { EIP712 } from '@solidstate/contracts/cryptography/EIP712.sol';\n\nimport { VaultParentPermitStorage } from './VaultParentPermitStorage.sol';\nimport { VaultParentPermitLib, IVaultParentPermit } from './VaultParentPermitLib.sol';\nimport { TrustlessPermit } from '../lib/TrustlessPermit.sol';\n\n/**\n * @title   VaultParentPermitInternal\n * @notice  Adds EIP712 Permit functionality to the VaultParent\n * @dev     Users can have their withdraws or deposits relayed,\n * @dev     by signing a message with their private key.\n */\n\nabstract contract VaultParentPermitInternal is IVaultParentPermit {\n    using VaultParentPermitLib for DepositPermit;\n    using VaultParentPermitLib for WithdrawPermit;\n    using ECDSA for bytes32;\n    using TrustlessPermit for address;\n\n    string public constant version = '1';\n    bytes32 public constant VERSION_HASH = keccak256(bytes(version));\n\n    error VaultParentPermit__InvalidParams();\n    error VaultParentPermit__NonMatchingSigners();\n    error VaultParentPermit__InvalidNonce();\n    error VaultParentPermit__Deadline();\n\n    /**\n     * @notice  Gets the signer of the deposit permit from the signature\n     * @dev     Reverts if the signer of the deposit permit is not the signer of the ERC20 permit\n     * @dev     Reverts if the permit is past its deadline\n     * @param   depositPermitParams  the deposit permit params\n     * @return  signer  the signer of the deposit permit\n     */\n    function _depositPermitVerifyGetSigner(\n        DepositPermit memory depositPermitParams\n    ) internal returns (address signer) {\n        if (block.timestamp > depositPermitParams.deadline) {\n            revert VaultParentPermit__Deadline();\n        }\n\n        if (\n            depositPermitParams.depositAmount !=\n            depositPermitParams.erc20Permit.value\n        ) {\n            revert VaultParentPermit__InvalidParams();\n        }\n\n        signer = _getSigner(\n            depositPermitParams.hash(),\n            depositPermitParams.signature,\n            depositPermitParams.signerNonce\n        );\n\n        // This is very important because it also acts as a InvalidSignature signature check\n        // ie if the deposit parameters are changed after signing\n        if (signer != depositPermitParams.erc20Permit.owner) {\n            revert VaultParentPermit__NonMatchingSigners();\n        }\n\n        depositPermitParams.erc20Permit.token.trustlessPermit(\n            depositPermitParams.erc20Permit.owner,\n            address(this),\n            depositPermitParams.erc20Permit.value,\n            depositPermitParams.erc20Permit.deadline,\n            depositPermitParams.erc20Permit.v,\n            depositPermitParams.erc20Permit.r,\n            depositPermitParams.erc20Permit.s\n        );\n\n        _useNonce(signer, depositPermitParams.signerNonce);\n    }\n\n    /**\n     * @notice  Gets the signer of the withdraw permit from the signature\n     * @dev     Reverts if the permit is past its deadline\n     * @param   withdrawPermitParams  .\n     * @return  signer  .\n     */\n    function _withdrawPermitVerifyGetSigner(\n        WithdrawPermit memory withdrawPermitParams\n    ) internal returns (address signer) {\n        if (block.timestamp > withdrawPermitParams.deadline) {\n            revert VaultParentPermit__Deadline();\n        }\n\n        signer = _getSigner(\n            withdrawPermitParams.hash(),\n            withdrawPermitParams.signature,\n            withdrawPermitParams.signerNonce\n        );\n\n        _useNonce(signer, withdrawPermitParams.signerNonce);\n    }\n\n    /**\n     * @notice  Recovers the signer from the signature\n     * @dev     Checks to make sure the payloads nonce has not be used\n     * @param   structHash  the hash of the payload\n     * @param   signature  the signature of the payload\n     * @param   payloadNonce  the nonce of the payload\n     */\n    function _getSigner(\n        bytes32 structHash,\n        bytes memory signature,\n        uint256 payloadNonce\n    ) internal returns (address signer) {\n        bytes32 hash = keccak256(\n            abi.encodePacked(uint16(0x1901), _DOMAIN_SEPARATOR(), structHash)\n        );\n\n        // recover signer\n        signer = hash.recover(signature);\n\n        if (\n            VaultParentPermitStorage.layout().signerNonces[signer][payloadNonce]\n        ) {\n            revert VaultParentPermit__InvalidNonce();\n        }\n    }\n\n    function _useNonce(address signer, uint256 nonce) internal {\n        VaultParentPermitStorage.layout().signerNonces[signer][nonce] = true;\n    }\n\n    /**\n     * @notice  Returns the domain separator for the current chain\n     * @return  bytes32  domain separator\n     */\n    function _DOMAIN_SEPARATOR() internal returns (bytes32) {\n        VaultParentPermitStorage.Layout storage l = VaultParentPermitStorage\n            .layout();\n\n        if (l.domainSeparators[block.chainid] == 0x00) {\n            l.domainSeparators[block.chainid] = EIP712.calculateDomainSeparator(\n                keccak256(bytes(_name())),\n                VERSION_HASH\n            );\n        }\n\n        return l.domainSeparators[block.chainid];\n    }\n\n    /**\n     * @notice  EIP712 Requires name for the domain\n     * @dev     Enforces the upstream consumer to have name\n     * @return  string  name\n     */\n    function _name() internal view virtual returns (string memory);\n}\n"
      },
      "contracts/vault-parent/VaultParentPermitLib.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\n/**\n * @title   IVaultParentPermit\n * @dev     Structs for VaultParentPermit\n */\n\ninterface IVaultParentPermit {\n    struct ERC2612Permit {\n        address owner;\n        address token;\n        uint value;\n        uint256 deadline;\n        uint8 v;\n        bytes32 r;\n        bytes32 s;\n    }\n\n    // To create an immediate withdraw\n    // Set the triggerAbove to false\n    // And the unitPriceTrigger to 3% below the current price\n    struct WithdrawPermit {\n        uint tokenId;\n        uint shares;\n        uint unitPriceTrigger;\n        bool triggerAbove; // take profit == true // stop loss == false\n        uint deadline;\n        uint signerNonce;\n        bytes signature;\n    }\n\n    struct DepositPermit {\n        uint tokenId;\n        uint depositAmount;\n        uint acceptableUnitPrice;\n        address referrer;\n        uint deadline;\n        uint signerNonce;\n        bytes signature;\n        ERC2612Permit erc20Permit;\n    }\n}\n\n/**\n * @title   VaultParentPermitLib\n * @dev     Hashing and signatures for VaultParentPermit\n */\nlibrary VaultParentPermitLib {\n    bytes32 internal constant DEPOSIT_PERMIT_EIP712_TYPE_HASH =\n        keccak256(\n            'DepositPermit('\n            'uint256 tokenId,'\n            'uint256 depositAmount,'\n            'uint256 acceptableUnitPrice,'\n            'address referrer,'\n            'uint256 deadline,'\n            'uint256 signerNonce)'\n        );\n\n    bytes32 internal constant WITHDRAW_PERMIT_EIP712_TYPE_HASH =\n        keccak256(\n            'WithdrawPermit('\n            'uint256 tokenId,'\n            'uint256 shares,'\n            'uint256 unitPriceTrigger,'\n            'bool triggerAbove,'\n            'uint256 deadline,'\n            'uint256 signerNonce)'\n        );\n\n    /**\n     * @notice  Returns the EIP712 hash of a DepositPermit\n     * @dev     This is used to reconstruct the hash from the parameters\n     * @dev     Must match DEPOSIT_PERMIT_EIP712_TYPE_HASH\n     * @param   queueDepositParams  the DepositPermit struct\n     * @return  bytes32  the hash of the DepositPermit params\n     */\n    function hash(\n        IVaultParentPermit.DepositPermit memory queueDepositParams\n    ) internal pure returns (bytes32) {\n        return\n            keccak256(\n                abi.encode(\n                    DEPOSIT_PERMIT_EIP712_TYPE_HASH,\n                    queueDepositParams.tokenId,\n                    queueDepositParams.depositAmount,\n                    queueDepositParams.acceptableUnitPrice,\n                    queueDepositParams.referrer,\n                    queueDepositParams.deadline,\n                    queueDepositParams.signerNonce\n                )\n            );\n    }\n\n    /**\n     * @notice  Returns the EIP712 hash of a WithdrawPermit\n     * @dev     This is used to reconstruct the hash from the parameters\n     * @dev     Must match WITHDRAW_PERMIT_EIP712_TYPE_HASH\n     * @param   withdrawPermitParams  the WithdrawPermit struct\n     * @return  bytes32  the hash of the WithdrawPermit params\n     */\n    function hash(\n        IVaultParentPermit.WithdrawPermit memory withdrawPermitParams\n    ) internal pure returns (bytes32) {\n        return\n            keccak256(\n                abi.encode(\n                    WITHDRAW_PERMIT_EIP712_TYPE_HASH,\n                    withdrawPermitParams.tokenId,\n                    withdrawPermitParams.shares,\n                    withdrawPermitParams.unitPriceTrigger,\n                    withdrawPermitParams.triggerAbove,\n                    withdrawPermitParams.deadline,\n                    withdrawPermitParams.signerNonce\n                )\n            );\n    }\n}\n"
      },
      "contracts/vault-parent/VaultParentPermitStorage.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nlibrary VaultParentPermitStorage {\n    bytes32 internal constant STORAGE_SLOT =\n        keccak256('valio.storage.vaultParentPermit');\n\n    // solhint-disable-next-line ordering\n    struct Layout {\n        // Mapping of ChainID to domain separators. This is a very gas efficient way\n        // to not recalculate the domain separator on every call, while still\n        // automatically detecting ChainID changes.\n        mapping(uint256 => bytes32) domainSeparators;\n        // Signer -> usedNonces\n        mapping(address => mapping(uint256 => bool)) signerNonces;\n    }\n\n    function layout() internal pure returns (Layout storage l) {\n        bytes32 slot = STORAGE_SLOT;\n\n        assembly {\n            l.slot := slot\n        }\n    }\n}\n"
      },
      "contracts/vault-parent/VaultParentProxy.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nimport { Proxy } from '@solidstate/contracts/proxy/Proxy.sol';\nimport { IDiamondReadable } from '@solidstate/contracts/proxy/diamond/readable/IDiamondReadable.sol';\n\n/**\n * @title   VaultParentProxy\n * @dev     An instance of this is created when a manager creates a Vault\n * @notice  This proxies to the VaultParentDiamond which is its `implementation`\n */\ncontract VaultParentProxy is Proxy {\n    address private immutable DIAMOND;\n\n    constructor(address diamond) {\n        DIAMOND = diamond;\n    }\n\n    function _getImplementation() internal view override returns (address) {\n        return IDiamondReadable(DIAMOND).facetAddress(msg.sig);\n    }\n}\n"
      },
      "contracts/vault-parent/VaultParentStorage.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nlibrary VaultParentStorage {\n    bytes32 internal constant STORAGE_SLOT =\n        keccak256('valio.storage.vaultParent');\n\n    // solhint-disable-next-line ordering\n    struct ChainValue {\n        uint minValue;\n        uint lastUpdate;\n        uint maxValue;\n        bool hasHardDeprecatedAsset;\n    }\n\n    // solhint-disable-next-line ordering\n    struct Layout {\n        bytes32 _deprecated_vaultId;\n        bool childCreationInProgress;\n        bool bridgeInProgress;\n        uint lastBridgeCancellation;\n        uint withdrawsInProgress;\n        uint16[] childChains;\n        // chainId => childVault address\n        mapping(uint16 => address) children;\n        mapping(uint16 => ChainValue) chainTotalValues;\n        uint16 bridgeApprovedFor;\n        // Not a big fan of inverted flags, but some vaults were already deployed.\n        // Would have preferred to have childIsActive\n        mapping(uint16 => bool) childIsInactive;\n        bool vaultClosed;\n    }\n\n    function layout() internal pure returns (Layout storage l) {\n        bytes32 slot = STORAGE_SLOT;\n\n        assembly {\n            l.slot := slot\n        }\n    }\n}\n"
      },
      "contracts/vault-parent/VaultParentTransport.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nimport { ITransport } from '../transport/ITransport.sol';\nimport { VaultParentInternal } from '../vault-parent/VaultParentInternal.sol';\nimport { VaultParentStorage } from './VaultParentStorage.sol';\n\ncontract VaultParentTransport is VaultParentInternal {\n    event ReceivedChildValue();\n    event ReceivedWithdrawComplete(uint withdrawsStillInProgress);\n    event ReceivedChildCreated(uint16 childChainId, address childVault);\n\n    ///\n    /// Receivers/CallBacks\n    ///\n\n    function receiveWithdrawComplete() external onlyTransport {\n        VaultParentStorage.Layout storage l = VaultParentStorage.layout();\n\n        l.withdrawsInProgress--;\n        _registry().emitEvent();\n        emit ReceivedWithdrawComplete(l.withdrawsInProgress);\n    }\n\n    // Callback for once the sibling has been created on the dstChain\n    function receiveChildCreated(\n        uint16 childChainId,\n        address childVault\n    ) external onlyTransport {\n        VaultParentStorage.Layout storage l = VaultParentStorage.layout();\n\n        if (l.children[childChainId] == address(0)) {\n            l.childCreationInProgress = false;\n            l.childIsInactive[childChainId] = true;\n            for (uint8 i = 0; i < l.childChains.length; i++) {\n                // Federate the new sibling to the other children\n                _registry().transport().sendAddSiblingRequest(\n                    ITransport.AddVaultSiblingRequest({\n                        // The existing child\n                        child: ITransport.ChildVault({\n                            vault: l.children[l.childChains[i]],\n                            chainId: l.childChains[i]\n                        }),\n                        // The new Sibling\n                        newSibling: ITransport.ChildVault({\n                            vault: childVault,\n                            chainId: childChainId\n                        })\n                    })\n                );\n            }\n            // It's important these are here and not before the for loop\n            // We only want to iterate over the existing children\n            l.children[childChainId] = childVault;\n            l.childChains.push(childChainId);\n\n            _registry().emitEvent();\n            emit ReceivedChildCreated(childChainId, childVault);\n        }\n    }\n\n    // Callback to notify the parent the bridge has taken place\n    function receiveBridgedAssetAcknowledgement(\n        uint16 receivingChainId\n    ) external onlyTransport {\n        VaultParentStorage.Layout storage l = VaultParentStorage.layout();\n        // While a bridge is underway everything is locked (deposits/withdraws etc)\n        // Once the bridge is complete we need to clear the stale values we have for the childVaults\n        // If a requestTotalSync completes (which is valid for 10 mins),\n        // then a bridge takes place from a child to the parent and completes within 10 mins,\n        // then the parent will have stale values for the childVaults but the extra value from the bridge\n        // This enforces that a requestTotalSync must happen after a bridge completes.\n        for (uint8 i = 0; i < l.childChains.length; i++) {\n            l.chainTotalValues[l.childChains[i]].lastUpdate = 0;\n        }\n        // Update the childChain to be active\n        l.childIsInactive[receivingChainId] = false;\n        l.bridgeInProgress = false;\n        l.bridgeApprovedFor = 0;\n    }\n\n    // Allows the bridge approval to be cancelled by the receiver\n    // after a period of time if the bridge doesn't take place\n    function receiveBridgeApprovalCancellation(\n        address requester\n    ) external onlyTransport {\n        VaultParentStorage.Layout storage l = VaultParentStorage.layout();\n\n        l.bridgeInProgress = false;\n        l.bridgeApprovedFor = 0;\n        if (requester != _manager()) {\n            l.lastBridgeCancellation = block.timestamp;\n        }\n    }\n\n    // Callback to receive value/supply updates\n    function receiveChildValue(\n        uint16 childChainId,\n        uint minValue,\n        uint maxValue,\n        uint time,\n        bool hasHardDeprecatedAsset\n    ) external onlyTransport {\n        // We don't accept value updates while WithdrawInProgress\n        // As the value could be stale (from before the withdraw is executed)\n        // We also don't allow requestTotalValueUpdateMultiChain to be called\n        // until all withdraw processing on all chains is complete.\n        // We adjust the min and maxValues proportionally after each withdraw\n        if (!_withdrawInProgress()) {\n            VaultParentStorage.Layout storage l = VaultParentStorage.layout();\n\n            l.chainTotalValues[childChainId] = VaultParentStorage.ChainValue({\n                minValue: minValue,\n                maxValue: maxValue,\n                lastUpdate: time,\n                hasHardDeprecatedAsset: hasHardDeprecatedAsset\n            });\n\n            _registry().emitEvent();\n            emit ReceivedChildValue();\n        }\n    }\n\n    ///\n    /// All of the below need to be moved to a VaultParentExternal Contract\n    /// Moved here temporarily to avoid contract sizing issues\n    ///\n\n    /**\n     * @notice  Returns the lz fee for the give function\n     * @dev     This is a helper method for the frontend\n     * @dev     We use the sighash of the intended function call to identify the action\n     * @param   sigHash  The sighash of the intended function call\n     * @param   chainId  The destination lz chain id\n     * @return  fee  The lz fee for the message + destination gas\n     */\n    function getLzFee(\n        bytes4 sigHash,\n        uint16 chainId\n    ) external view returns (uint fee) {\n        return _getLzFee(sigHash, chainId);\n    }\n\n    /**\n     * @notice  Returns the lzFees for a given sigHash\n     * @dev     The sigHash is the 4 byte hash of the function that will be called.\n     * @dev     E.G For withdrawal a message will be sent to each child chain\n     * @param   sigHash  The hash of the function signature\n     * @return  lzFees  The fees to send the message to each child chain\n     * @return  totalSendFee  The total fee to send the message to all child chains\n     */\n    function getLzFeesMultiChain(\n        bytes4 sigHash\n    ) external view returns (uint[] memory lzFees, uint256 totalSendFee) {\n        return _getLzFeesMultiChain(sigHash, _allChildChains());\n    }\n\n    /**\n     * @notice  Returns the lzChainId for a given index\n     * @dev     The childChains are ie [101, 111]\n     * @param   index  The index of the childChain\n     * @return  uint16  The lzChainId\n     */\n    function childChains(uint index) external view returns (uint16) {\n        return _childChains(index);\n    }\n\n    /**\n     * @notice  Returns the child vault address for a given chainId\n     * @param   chainId  The chainId of the child\n     * @return  address  The child vault address\n     */\n    function children(uint16 chainId) external view returns (address) {\n        return _children(chainId);\n    }\n\n    /**\n     * @notice  Returns which chains the parent vault has children\n     * @dev     These are lzChainIds, ideally we should have used chainIds\n     * @return  uint16[]  An array of lzChainIds\n     */\n    function allChildChains() external view returns (uint16[] memory) {\n        return _allChildChains();\n    }\n\n    /**\n     * @notice  Returns the AUM of the parent and all children\n     * @dev     Will revert if the vault is not in sync\n     * @dev     Will skip children where if no funds have ever been sent there\n     * @return  minValue  The min value of the parent and all children\n     * @return  maxValue  The max value of the parent and all children\n     * @return  hasHardDeprecatedAsset  If any of the vaults hold a hard deprecated asset\n     */\n    function totalValueAcrossAllChains()\n        external\n        view\n        returns (uint minValue, uint maxValue, bool hasHardDeprecatedAsset)\n    {\n        return _totalValueAcrossAllChains();\n    }\n\n    /**\n     * @notice  Returns if the vault has a fresh vault value from all children\n     * @dev     If the value has been received < `livelinessThreshold`, it is considered fresh\n     * @return  bool  If the vault is in sync\n     */\n    function inSync() external view returns (bool) {\n        return _inSync();\n    }\n\n    /**\n     * @notice  Returns if the vault is in the process of executing withdraws\n     * @dev     This will be false once all child vaults report the withdraw request is complete\n     * @dev     Note: multiple withdraws can be processed at once\n     * @return  bool  If the vault is in the process of executing withdraws\n     */\n    function withdrawInProgress() external view returns (bool) {\n        return _withdrawInProgress();\n    }\n\n    /**\n     * @notice  Returns if a sync is required to process a withdraw for the given tokenId\n     * @dev     tokenIds that are precluded from paying performance fees do not require a sync\n     * @dev     This means if a manager does not have a performance fee this is all tokenIds\n     * @param   tokenId  The tokenId of the holding\n     * @return  bool  If a sync is required to process a withdraw\n     */\n    function requiresSyncForWithdraw(\n        uint tokenId\n    ) external view returns (bool) {\n        return _requiresSyncForFees(tokenId);\n    }\n\n    /**\n     * @notice  Returns if a sync is required to process a deposit\n     * @dev     If the vault has active children, a sync is required\n     * @dev     This is purely a helper method for the frontend\n     * @return  bool  If a sync is required to process a deposit\n     */\n    function requiresSyncForDeposit() external view returns (bool) {\n        return _requiresSyncForDeposit();\n    }\n\n    // Returns the number of seconds until the totalValueSync expires\n    /**\n     * @notice  Returns the number of seconds until the totalValueSync expires\n     * @dev     If the vault is not in sync, this will be 0\n     * @dev     Not if there is two children this will return the lowest tte\n     * @return  uint  The number of seconds until the totalValueSync expires\n     */\n    function timeUntilExpiry() external view returns (uint) {\n        return _timeUntilExpiry();\n    }\n\n    /**\n     * @notice  Returns if a holding is locked and cannot be withdraw from\n     * @dev     Helper function for the frontend\n     * @param   tokenId  The tokenId of the holding\n     * @return  bool  If the holding is locked\n     */\n    function holdingLocked(uint tokenId) external view returns (bool) {\n        return _holdingLocked(tokenId);\n    }\n\n    /**\n     * @notice  Returns if a sync is required to process a deposit\n     * @dev     If the vault has active children, a sync is required\n     * @dev     This is purely a helper method for the frontend\n     * @return  bool  If a sync is required to process a deposit\n     */\n    function _requiresSyncForDeposit() internal view returns (bool) {\n        if (_hasActiveChildren()) {\n            return true;\n        }\n        return false;\n    }\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "libraries": {}
    }
  }}