creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "contracts/dependencies/chainlink/AggregatorV3Interface.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// Chainlink Contracts v0.4.0 (v0.8/interfaces/AggregatorV3Interface.sol)\npragma solidity ^0.8.0;\n\ninterface AggregatorV3Interface {\n    function decimals() external view returns (uint8);\n\n    function description() external view returns (string memory);\n\n    function version() external view returns (uint256);\n\n    // getRoundData and latestRoundData should both raise \"No data present\"\n    // if they do not have data to report, instead of returning unset values\n    // which could be misinterpreted as actual reported values.\n    function getRoundData(\n        uint80 _roundId\n    )\n        external\n        view\n        returns (\n            uint80 roundId,\n            int256 answer,\n            uint256 startedAt,\n            uint256 updatedAt,\n            uint80 answeredInRound\n        );\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/dependencies/openzeppelin/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `from` to `to` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n"
      },
      "contracts/dependencies/openzeppelin/utils/structs/EnumerableSet.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n *     // Add the library methods\n *     using EnumerableSet for EnumerableSet.AddressSet;\n *\n *     // Declare a set state variable\n *     EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n    // To implement this library for multiple types with as little code\n    // repetition as possible, we write it in terms of a generic Set type with\n    // bytes32 values.\n    // The Set implementation uses private functions, and user-facing\n    // implementations (such as AddressSet) are just wrappers around the\n    // underlying Set.\n    // This means that we can only create new EnumerableSets for types that fit\n    // in bytes32.\n\n    struct Set {\n        // Storage of set values\n        bytes32[] _values;\n        // Position of the value in the `values` array, plus 1 because index 0\n        // means a value is not in the set.\n        mapping(bytes32 => uint256) _indexes;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function _add(Set storage set, bytes32 value) private returns (bool) {\n        if (!_contains(set, value)) {\n            set._values.push(value);\n            // The value is stored at length-1, but we add 1 to all indexes\n            // and use 0 as a sentinel value\n            set._indexes[value] = set._values.length;\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function _remove(Set storage set, bytes32 value) private returns (bool) {\n        // We read and store the value's index to prevent multiple reads from the same storage slot\n        uint256 valueIndex = set._indexes[value];\n\n        if (valueIndex != 0) {\n            // Equivalent to contains(set, value)\n            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n            // the array, and then remove the last element (sometimes called as 'swap and pop').\n            // This modifies the order of the array, as noted in {at}.\n\n            uint256 toDeleteIndex = valueIndex - 1;\n            uint256 lastIndex = set._values.length - 1;\n\n            if (lastIndex != toDeleteIndex) {\n                bytes32 lastValue = set._values[lastIndex];\n\n                // Move the last value to the index where the value to delete is\n                set._values[toDeleteIndex] = lastValue;\n                // Update the index for the moved value\n                set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\n            }\n\n            // Delete the slot where the moved value was stored\n            set._values.pop();\n\n            // Delete the index for the deleted slot\n            delete set._indexes[value];\n\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function _contains(Set storage set, bytes32 value) private view returns (bool) {\n        return set._indexes[value] != 0;\n    }\n\n    /**\n     * @dev Returns the number of values on the set. O(1).\n     */\n    function _length(Set storage set) private view returns (uint256) {\n        return set._values.length;\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function _at(Set storage set, uint256 index) private view returns (bytes32) {\n        return set._values[index];\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function _values(Set storage set) private view returns (bytes32[] memory) {\n        return set._values;\n    }\n\n    // Bytes32Set\n\n    struct Bytes32Set {\n        Set _inner;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n        return _add(set._inner, value);\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n        return _remove(set._inner, value);\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n        return _contains(set._inner, value);\n    }\n\n    /**\n     * @dev Returns the number of values in the set. O(1).\n     */\n    function length(Bytes32Set storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n        return _at(set._inner, index);\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n        bytes32[] memory store = _values(set._inner);\n        bytes32[] memory result;\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := store\n        }\n\n        return result;\n    }\n\n    // AddressSet\n\n    struct AddressSet {\n        Set _inner;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(AddressSet storage set, address value) internal returns (bool) {\n        return _add(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(AddressSet storage set, address value) internal returns (bool) {\n        return _remove(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(AddressSet storage set, address value) internal view returns (bool) {\n        return _contains(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    /**\n     * @dev Returns the number of values in the set. O(1).\n     */\n    function length(AddressSet storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(AddressSet storage set, uint256 index) internal view returns (address) {\n        return address(uint160(uint256(_at(set._inner, index))));\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(AddressSet storage set) internal view returns (address[] memory) {\n        bytes32[] memory store = _values(set._inner);\n        address[] memory result;\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := store\n        }\n\n        return result;\n    }\n\n    // UintSet\n\n    struct UintSet {\n        Set _inner;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(UintSet storage set, uint256 value) internal returns (bool) {\n        return _add(set._inner, bytes32(value));\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(UintSet storage set, uint256 value) internal returns (bool) {\n        return _remove(set._inner, bytes32(value));\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n        return _contains(set._inner, bytes32(value));\n    }\n\n    /**\n     * @dev Returns the number of values in the set. O(1).\n     */\n    function length(UintSet storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n        return uint256(_at(set._inner, index));\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(UintSet storage set) internal view returns (uint256[] memory) {\n        bytes32[] memory store = _values(set._inner);\n        uint256[] memory result;\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := store\n        }\n\n        return result;\n    }\n}\n"
      },
      "contracts/protocol/interfaces/IAddressResolver.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\ninterface IAddressResolver {\n    error UnmatchedInputs();\n\n    event AddressImported(bytes32 name, address destination);\n\n    function getAddress(bytes32 name, string calldata reason) external view returns (address);\n\n    function getAddress(bytes32 name) external view returns (address);\n\n    function getAddresses() external view returns (address[] memory);\n\n    function getNames() external view returns (bytes32[] memory);\n}\n"
      },
      "contracts/protocol/interfaces/IBeaconProxyController.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\ninterface IBeaconProxyController {\n    error NoBeaconProxyContract();\n    error InvalidProxyContract();\n\n    event BeaconProxyUpdated(\n        bytes32 indexed id,\n        address indexed proxyAddress,\n        address indexed newImplementationAddress,\n        address oldImplementationAddress\n    );\n\n    function getBeaconProxyAddress(bytes32 beaconName) external view returns (address);\n\n    function setFutureValueVaultImpl(address newImpl) external;\n\n    function setLendingMarketImpl(address newImpl) external;\n\n    function setZCTokenImpl(address newImpl) external;\n\n    function deployFutureValueVault() external returns (address futureValueVault);\n\n    function deployLendingMarket(\n        bytes32 ccy,\n        uint256 orderFeeRate,\n        uint256 cbLimitRange\n    ) external returns (address market);\n\n    function deployZCToken(\n        string memory name,\n        string memory symbol,\n        uint8 decimals,\n        address asset,\n        uint256 maturity\n    ) external returns (address futureValueToken);\n}\n"
      },
      "contracts/protocol/interfaces/ICurrencyController.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\nimport {PriceFeed} from \"../storages/CurrencyControllerStorage.sol\";\n\n/**\n * @dev Currency Controller contract is responsible for managing supported\n * currencies in Secured Finance Protocol\n *\n * Contract links new currencies to ETH Chainlink price feeds, without existing price feed\n * contract owner is not able to add a new currency into the protocol\n */\ninterface ICurrencyController {\n    error InvalidCurrency();\n    error InvalidHaircut();\n    error InvalidPriceFeed();\n    error InvalidDecimals(address priceFeed, uint8 decimals);\n    error InvalidPriceFeedInputs();\n    error StalePriceFeed(\n        address priceFeed,\n        uint256 heartbeat,\n        uint256 updatedAt,\n        uint256 blockTimestamp\n    );\n\n    event CurrencyAdded(bytes32 indexed ccy, uint256 haircut);\n    event CurrencyRemoved(bytes32 indexed ccy);\n\n    event HaircutUpdated(bytes32 indexed ccy, uint256 haircut);\n\n    event PriceFeedUpdated(bytes32 ccy, uint256 decimals, address[] indexed priceFeeds);\n\n    function convert(\n        bytes32 _fromCcy,\n        bytes32 _toCcy,\n        uint256 _amount\n    ) external view returns (uint256 amount);\n\n    function convert(\n        bytes32 _fromCcy,\n        bytes32 _toCcy,\n        uint256[] calldata _amounts\n    ) external view returns (uint256[] memory amounts);\n\n    function convertToBaseCurrency(\n        bytes32 _ccy,\n        uint256 _amount\n    ) external view returns (uint256 amount);\n\n    function convertToBaseCurrency(\n        bytes32 _ccy,\n        int256 _amount\n    ) external view returns (int256 amount);\n\n    function convertToBaseCurrency(\n        bytes32 _ccy,\n        uint256[] calldata _amounts\n    ) external view returns (uint256[] memory amounts);\n\n    function convertFromBaseCurrency(\n        bytes32 _ccy,\n        uint256 _amountETH\n    ) external view returns (uint256 amount);\n\n    function convertFromBaseCurrency(\n        bytes32 _ccy,\n        uint256[] calldata _amounts\n    ) external view returns (uint256[] memory amounts);\n\n    function getDecimals(bytes32) external view returns (uint8);\n\n    function getCurrencies() external view returns (bytes32[] memory);\n\n    function getHaircut(bytes32 _ccy) external view returns (uint256);\n\n    function getPriceFeed(bytes32 _ccy) external view returns (PriceFeed memory);\n\n    function getLastPrice(bytes32 _ccy) external view returns (int256 price);\n\n    function getAggregatedLastPrice(bytes32 _ccy) external view returns (int256);\n\n    function currencyExists(bytes32 _ccy) external view returns (bool);\n\n    function updatePriceFeed(\n        bytes32 _ccy,\n        uint8 _decimals,\n        address[] calldata _priceFeeds,\n        uint256[] calldata _heartbeats\n    ) external;\n\n    function addCurrency(\n        bytes32 _ccy,\n        uint8 _decimals,\n        uint256 _haircut,\n        address[] calldata _priceFeeds,\n        uint256[] calldata _heartbeats\n    ) external;\n\n    function updateHaircut(bytes32 _ccy, uint256 _haircut) external;\n\n    function removeCurrency(bytes32 _ccy) external;\n}\n"
      },
      "contracts/protocol/interfaces/IGenesisValueVault.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\nimport {AutoRollLog} from \"../storages/GenesisValueVaultStorage.sol\";\n\ninterface IGenesisValueVault {\n    error NoCompoundFactorExists(uint256 maturity);\n    error CompoundFactorIsZero();\n    error ResidualAmountIsNotZero();\n    error UnitPriceIsZero();\n    error InvalidMaturity();\n    error InvalidAmount();\n    error InvalidOrderFeeRate();\n    error CurrencyAlreadyInitialized();\n    error InitialCompoundFactorAlreadyFinalized();\n    error AutoRollLogAlreadyUpdated(uint256 currentMaturity, uint256 nextMaturity);\n    error InsufficientBalance();\n    error InsufficientLockedBalance();\n\n    event Transfer(bytes32 indexed ccy, address indexed from, address indexed to, int256 value);\n    event AutoRollExecuted(\n        bytes32 indexed ccy,\n        uint256 lendingCompoundFactor,\n        uint256 borrowingCompoundFactor,\n        uint256 unitPrice,\n        uint256 currentMaturity,\n        uint256 previousMaturity\n    );\n    event BalanceLocked(bytes32 indexed ccy, address indexed user, uint256 value);\n    event BalanceUnlocked(bytes32 indexed ccy, address indexed user, uint256 value);\n\n    function isAutoRolled(bytes32 _ccy, uint256 _maturity) external view returns (bool);\n\n    function isInitialized(bytes32 ccy) external view returns (bool);\n\n    function decimals(bytes32 ccy) external view returns (uint8);\n\n    function getTotalLendingSupply(bytes32 ccy) external view returns (uint256);\n\n    function getTotalBorrowingSupply(bytes32 ccy) external view returns (uint256);\n\n    function getBalance(bytes32 ccy, address user) external view returns (int256);\n\n    function getMaturityGenesisValue(bytes32 ccy, uint256 maturity) external view returns (int256);\n\n    function getCurrentMaturity(bytes32 ccy) external view returns (uint256);\n\n    function getLendingCompoundFactor(bytes32 ccy) external view returns (uint256);\n\n    function getBorrowingCompoundFactor(bytes32 ccy) external view returns (uint256);\n\n    function getAutoRollLog(\n        bytes32 ccy,\n        uint256 maturity\n    ) external view returns (AutoRollLog memory);\n\n    function getLatestAutoRollLog(bytes32 ccy) external view returns (AutoRollLog memory);\n\n    function getTotalLockedBalance(bytes32 ccy) external view returns (uint256);\n\n    function calculateFVFromFV(\n        bytes32 ccy,\n        uint256 basisMaturity,\n        uint256 destinationMaturity,\n        int256 futureValue\n    ) external view returns (int256);\n\n    function calculateGVFromFV(\n        bytes32 ccy,\n        uint256 basisMaturity,\n        int256 futureValue\n    ) external view returns (int256);\n\n    function calculateFVFromGV(\n        bytes32 ccy,\n        uint256 basisMaturity,\n        int256 genesisValue\n    ) external view returns (int256);\n\n    function getBalanceFluctuationByAutoRolls(\n        bytes32 ccy,\n        address user,\n        uint256 maturity\n    ) external view returns (int256 fluctuation);\n\n    function calculateBalanceFluctuationByAutoRolls(\n        bytes32 ccy,\n        int256 balance,\n        uint256 fromMaturity,\n        uint256 toMaturity\n    ) external view returns (int256 fluctuation);\n\n    function initializeCurrencySetting(\n        bytes32 ccy,\n        uint8 decimals,\n        uint256 compoundFactor,\n        uint256 maturity\n    ) external;\n\n    function updateInitialCompoundFactor(bytes32 ccy, uint256 unitPrice) external;\n\n    function updateDecimals(bytes32 _ccy, uint8 _decimals) external;\n\n    function executeAutoRoll(\n        bytes32 ccy,\n        uint256 maturity,\n        uint256 nextMaturity,\n        uint256 unitPrice,\n        uint256 orderFeeRate\n    ) external;\n\n    function updateGenesisValueWithFutureValue(\n        bytes32 ccy,\n        address user,\n        uint256 basisMaturity,\n        int256 fvAmount\n    ) external;\n\n    function updateGenesisValueWithResidualAmount(\n        bytes32 ccy,\n        address user,\n        uint256 basisMaturity\n    ) external;\n\n    function lock(\n        bytes32 ccy,\n        address user,\n        uint256 amount\n    ) external returns (uint256 lockedAmount);\n\n    function unlock(bytes32 ccy, address user, uint256 amount) external;\n\n    function transferFrom(bytes32 ccy, address sender, address receiver, int256 amount) external;\n\n    function cleanUpBalance(bytes32 ccy, address user, uint256 maturity) external;\n\n    function executeForcedReset(bytes32 _ccy, address _user) external;\n\n    function executeForcedReset(\n        bytes32 _ccy,\n        uint256 _maturity,\n        address _user,\n        int256 _amountInFV\n    ) external returns (int256 removedAmount, int256 balance);\n}\n"
      },
      "contracts/protocol/interfaces/ILendingMarketController.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\nimport {ProtocolTypes} from \"../types/ProtocolTypes.sol\";\nimport {ZCTokenInfo, TerminationCurrencyCache} from \"../storages/LendingMarketControllerStorage.sol\";\n\ninterface ILendingMarketController {\n    error InvalidMaturity();\n    error InvalidCurrency();\n    error MarketTerminated();\n    error NotTerminated();\n    error AlreadyInitialized();\n\n    struct AdditionalFunds {\n        bytes32 ccy;\n        uint256 workingLendOrdersAmount;\n        uint256 claimableAmount;\n        uint256 workingBorrowOrdersAmount;\n        uint256 debtAmount;\n        uint256 lentAmount;\n        uint256 borrowedAmount;\n    }\n\n    struct CalculatedTotalFunds {\n        uint256 plusDepositAmountInAdditionalFundsCcy;\n        uint256 minusDepositAmountInAdditionalFundsCcy;\n        uint256 workingLendOrdersAmount;\n        uint256 claimableAmount;\n        uint256 collateralAmount;\n        uint256 lentAmount;\n        uint256 workingBorrowOrdersAmount;\n        uint256 debtAmount;\n        uint256 borrowedAmount;\n    }\n\n    struct CalculatedFunds {\n        uint256 workingLendOrdersAmount;\n        uint256 claimableAmount;\n        uint256 collateralAmount;\n        uint256 unallocatedCollateralAmount;\n        uint256 lentAmount;\n        uint256 workingBorrowOrdersAmount;\n        uint256 debtAmount;\n        uint256 borrowedAmount;\n    }\n\n    struct GetOrderEstimationParams {\n        bytes32 ccy;\n        uint256 maturity;\n        address user;\n        ProtocolTypes.Side side;\n        uint256 amount;\n        uint256 unitPrice;\n        uint256 additionalDepositAmount;\n        bool ignoreBorrowedAmount;\n    }\n\n    function isValidMaturity(bytes32 _ccy, uint256 _maturity) external view returns (bool);\n\n    function isTerminated() external view returns (bool);\n\n    function isRedemptionRequired(address _user) external view returns (bool);\n\n    function getMarketBasePeriod() external view returns (uint256);\n\n    function getTerminationDate() external view returns (uint256);\n\n    function getTerminationCurrencyCache(\n        bytes32 _ccy\n    ) external view returns (TerminationCurrencyCache memory);\n\n    function getTerminationCollateralRatio(bytes32 _ccy) external view returns (uint256);\n\n    function getMinDebtUnitPrice(bytes32 _ccy) external view returns (uint256);\n\n    function getCurrentMinDebtUnitPrice(\n        bytes32 _ccy,\n        uint256 _maturity\n    ) external view returns (uint256);\n\n    function getGenesisDate(bytes32 ccy) external view returns (uint256);\n\n    function getLendingMarket(bytes32 ccy) external view returns (address);\n\n    function getFutureValueVault(bytes32 ccy) external view returns (address);\n\n    function getOrderBookId(bytes32 _ccy, uint256 _maturity) external view returns (uint8);\n\n    function getPendingOrderAmount(bytes32 _ccy, uint256 _maturity) external view returns (uint256);\n\n    function getOrderEstimation(\n        GetOrderEstimationParams calldata params\n    )\n        external\n        view\n        returns (\n            uint256 lastUnitPrice,\n            uint256 filledAmount,\n            uint256 filledAmountInFV,\n            uint256 orderFeeInFV,\n            uint256 placedAmount,\n            uint256 coverage,\n            bool isInsufficientDepositAmount\n        );\n\n    function getMaturities(bytes32 ccy) external view returns (uint256[] memory);\n\n    function getOrderBookIds(bytes32 ccy) external view returns (uint8[] memory);\n\n    function getUsedCurrencies(address user) external view returns (bytes32[] memory);\n\n    function getTotalPresentValue(bytes32 ccy, address user) external view returns (int256);\n\n    function getTotalPresentValueInBaseCurrency(\n        address user\n    ) external view returns (int256 totalPresentValue);\n\n    function getGenesisValue(\n        bytes32 ccy,\n        address user\n    ) external view returns (int256 amount, int256 amountInPV, int256 amountInFV);\n\n    function getPosition(\n        bytes32 _ccy,\n        uint256 _maturity,\n        address _user\n    ) external view returns (int256 presentValue, int256 futureValue);\n\n    function getZCToken(bytes32 ccy, uint256 maturity) external view returns (address);\n\n    function getZCTokenInfo(address zcToken) external view returns (ZCTokenInfo memory);\n\n    function getWithdrawableZCTokenAmount(\n        bytes32 ccy,\n        uint256 maturity,\n        address user\n    ) external view returns (uint256 amount);\n\n    function calculateFunds(\n        bytes32 ccy,\n        address user,\n        uint256 liquidationThresholdRate\n    ) external view returns (CalculatedFunds memory funds);\n\n    function calculateTotalFundsInBaseCurrency(\n        address user,\n        AdditionalFunds calldata _additionalFunds,\n        uint256 liquidationThresholdRate\n    ) external view returns (CalculatedTotalFunds memory calculatedFunds);\n\n    function isInitializedLendingMarket(bytes32 ccy) external view returns (bool);\n\n    function initializeLendingMarket(\n        bytes32 ccy,\n        uint256 genesisDate,\n        uint256 compoundFactor,\n        uint256 orderFeeRate,\n        uint256 circuitBreakerLimitRange,\n        uint256 minDebtUnitPrice\n    ) external;\n\n    function createOrderBook(bytes32 ccy, uint256 openingDate, uint256 preOpeningDate) external;\n\n    function executeOrder(\n        bytes32 ccy,\n        uint256 maturity,\n        ProtocolTypes.Side side,\n        uint256 amount,\n        uint256 unitPrice\n    ) external returns (bool);\n\n    function depositAndExecuteOrder(\n        bytes32 ccy,\n        uint256 maturity,\n        ProtocolTypes.Side side,\n        uint256 amount,\n        uint256 unitPrice\n    ) external payable returns (bool);\n\n    function depositWithPermitAndExecuteOrder(\n        bytes32 ccy,\n        uint256 maturity,\n        ProtocolTypes.Side side,\n        uint256 amount,\n        uint256 unitPrice,\n        uint256 deadline,\n        uint8 permitV,\n        bytes32 permitR,\n        bytes32 permitS\n    ) external returns (bool);\n\n    function executePreOrder(\n        bytes32 ccy,\n        uint256 maturity,\n        ProtocolTypes.Side side,\n        uint256 amount,\n        uint256 unitPrice\n    ) external returns (bool);\n\n    function depositAndExecutesPreOrder(\n        bytes32 ccy,\n        uint256 maturity,\n        ProtocolTypes.Side side,\n        uint256 amount,\n        uint256 unitPrice\n    ) external payable returns (bool);\n\n    function depositWithPermitAndExecutePreOrder(\n        bytes32 _ccy,\n        uint256 _maturity,\n        ProtocolTypes.Side _side,\n        uint256 _amount,\n        uint256 _unitPrice,\n        uint256 _deadline,\n        uint8 _permitV,\n        bytes32 _permitR,\n        bytes32 _permitS\n    ) external returns (bool);\n\n    function unwindPosition(bytes32 ccy, uint256 maturity) external returns (bool);\n\n    function executeItayoseCall(bytes32 ccy, uint256 maturity) external returns (bool);\n\n    function executeRedemption(bytes32 _ccy, uint256 _maturity) external returns (bool);\n\n    function executeRepayment(bytes32 _ccy, uint256 _maturity) external returns (bool);\n\n    function executeEmergencySettlement() external returns (bool);\n\n    function executeLiquidationCall(\n        bytes32 collateralCcy,\n        bytes32 debtCcy,\n        uint256 debtMaturity,\n        address user\n    ) external returns (bool);\n\n    function executeForcedRepayment(\n        bytes32 _collateralCcy,\n        bytes32 _debtCcy,\n        uint256 _debtMaturity,\n        address _user\n    ) external returns (bool);\n\n    function cancelOrder(bytes32 ccy, uint256 maturity, uint48 orderId) external returns (bool);\n\n    function rotateOrderBooks(bytes32 ccy) external;\n\n    function executeEmergencyTermination() external;\n\n    function pauseLendingMarket(bytes32 ccy) external returns (bool);\n\n    function unpauseLendingMarket(bytes32 ccy) external returns (bool);\n\n    function cleanUpAllFunds(address user) external returns (bool);\n\n    function cleanUpFunds(bytes32 ccy, address user) external returns (uint256 activeOrderCount);\n\n    function updateMinDebtUnitPrice(bytes32 _ccy, uint256 _minDebtUnitPrice) external;\n\n    function withdrawZCToken(bytes32 _ccy, uint256 _maturity, uint256 _amount) external;\n\n    function depositZCToken(bytes32 _ccy, uint256 _maturity, uint256 _amount) external;\n}\n"
      },
      "contracts/protocol/interfaces/INativeToken.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\nimport \"../../dependencies/openzeppelin/token/ERC20/IERC20.sol\";\n\ninterface INativeToken is IERC20 {\n    event Deposit(address user, uint256 amount);\n    event Withdrawal(address user, uint256 amount);\n\n    function deposit() external payable;\n\n    function withdraw(uint256 amount) external;\n}\n"
      },
      "contracts/protocol/interfaces/IReserveFund.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\ninterface IReserveFund {\n    event Pause(address account);\n    event Unpause(address account);\n\n    function isPaused() external view returns (bool);\n\n    function pause() external;\n\n    function unpause() external;\n\n    function deposit(bytes32 ccy, uint256 amount) external payable;\n\n    function withdraw(bytes32 ccy, uint256 amount) external;\n}\n"
      },
      "contracts/protocol/interfaces/ITokenVault.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\nimport {ProtocolTypes} from \"../types/ProtocolTypes.sol\";\nimport {ILendingMarketController} from \"../interfaces/ILendingMarketController.sol\";\n\ninterface ITokenVault {\n    error UnregisteredCurrency();\n    error InvalidCurrency();\n    error InvalidToken();\n    error InvalidAmount(bytes32 ccy, uint256 amount, uint256 msgValue);\n    error AmountIsZero();\n    error CallerNotBaseCurrency(address caller);\n    error MarketTerminated();\n    error RedemptionIsRequired();\n\n    event Deposit(address indexed user, bytes32 ccy, uint256 amount, address caller);\n    event Withdraw(address indexed user, bytes32 ccy, uint256 amount);\n    event Transfer(bytes32 indexed ccy, address indexed from, address indexed to, uint256 amount);\n    event CurrencyRegistered(bytes32 ccy, address tokenAddress, bool isCollateral);\n    event CurrencyUpdated(bytes32 ccy, bool isCollateral);\n\n    function isCovered(\n        address user,\n        bytes32 ccy\n    ) external view returns (bool isEnoughCollateral, bool isEnoughDepositInOrderCcy);\n\n    function isCollateral(bytes32 ccy) external view returns (bool);\n\n    function isCollateral(bytes32[] calldata ccys) external view returns (bool[] memory);\n\n    function isRegisteredCurrency(bytes32 ccy) external view returns (bool);\n\n    function getTokenAddress(bytes32 ccy) external view returns (address);\n\n    function getCollateralCurrencies() external view returns (bytes32[] memory);\n\n    function getWithdrawableCollateral(address user) external view returns (uint256);\n\n    function getWithdrawableCollateral(bytes32 ccy, address user) external view returns (uint256);\n\n    function getCoverage(address user) external view returns (uint256);\n\n    function getTotalUnusedCollateralAmount(address user) external view returns (uint256);\n\n    function getTotalCollateralAmount(address user) external view returns (uint256);\n\n    function getCollateralDetail(\n        address user\n    )\n        external\n        view\n        returns (uint256 totalCollateral, uint256 totalUsedCollateral, uint256 totalDeposit);\n\n    function getCollateralAmount(address user, bytes32 ccy) external view returns (uint256);\n\n    function getBorrowableAmount(address user, bytes32 ccy) external view returns (uint256);\n\n    function getLiquidationAmount(\n        address user,\n        bytes32 liquidationCcy,\n        uint256 liquidationAmountMaximum\n    ) external view returns (uint256 liquidationAmount, uint256 protocolFee, uint256 liquidatorFee);\n\n    function getTotalDepositAmount(bytes32 ccy) external view returns (uint256);\n\n    function getDepositAmount(address user, bytes32 ccy) external view returns (uint256);\n\n    function getUsedCurrencies(address user) external view returns (bytes32[] memory);\n\n    function calculateCoverage(\n        address user,\n        ILendingMarketController.AdditionalFunds memory funds\n    ) external view returns (uint256 coverage, bool isInsufficientDepositAmount);\n\n    function calculateLiquidationFees(\n        uint256 liquidationAmount\n    ) external view returns (uint256 protocolFee, uint256 liquidatorFee);\n\n    function registerCurrency(bytes32 ccy, address tokenAddress, bool isCollateral) external;\n\n    function updateCurrency(bytes32 ccy, bool isCollateral) external;\n\n    function deposit(bytes32 ccy, uint256 amount) external payable;\n\n    function depositTo(bytes32 ccy, uint256 amount, address onBehalfOf) external payable;\n\n    function depositFrom(address user, bytes32 ccy, uint256 amount) external payable;\n\n    function depositWithPermitTo(\n        bytes32 ccy,\n        uint256 amount,\n        address onBehalfOf,\n        uint256 deadline,\n        uint8 permitV,\n        bytes32 permitR,\n        bytes32 permitS\n    ) external;\n\n    function depositWithPermitFrom(\n        address user,\n        bytes32 ccy,\n        uint256 amount,\n        uint256 deadline,\n        uint8 permitV,\n        bytes32 permitR,\n        bytes32 permitS\n    ) external;\n\n    function withdraw(bytes32 ccy, uint256 amount) external;\n\n    function addDepositAmount(address user, bytes32 ccy, uint256 amount) external;\n\n    function removeDepositAmount(address user, bytes32 ccy, uint256 amount) external;\n\n    function cleanUpUsedCurrencies(address user, bytes32 ccy) external;\n\n    function executeForcedReset(address user, bytes32 ccy) external returns (uint256 removedAmount);\n\n    function transferFrom(\n        bytes32 ccy,\n        address sender,\n        address receiver,\n        uint256 amount\n    ) external returns (uint256 untransferredAmount);\n\n    function pause() external;\n\n    function unpause() external;\n\n    function getLiquidationThresholdRate() external view returns (uint256 rate);\n}\n"
      },
      "contracts/protocol/libraries/AddressResolverLib.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\nimport {Contracts} from \"../libraries/Contracts.sol\";\nimport {IBeaconProxyController} from \"../interfaces/IBeaconProxyController.sol\";\nimport {ICurrencyController} from \"../interfaces/ICurrencyController.sol\";\nimport {IGenesisValueVault} from \"../interfaces/IGenesisValueVault.sol\";\nimport {ILendingMarketController} from \"../interfaces/ILendingMarketController.sol\";\nimport {IReserveFund} from \"../interfaces/IReserveFund.sol\";\nimport {ITokenVault} from \"../interfaces/ITokenVault.sol\";\nimport {MixinAddressResolverStorage as Storage} from \"../storages/mixins/MixinAddressResolverStorage.sol\";\n\nlibrary AddressResolverLib {\n    error MissingAddress(string name);\n\n    function getAddress(bytes32 name) internal view returns (address) {\n        address _foundAddress = Storage.slot().addressCache[name];\n        if (_foundAddress == address(0)) revert MissingAddress(string(abi.encodePacked(name)));\n        return _foundAddress;\n    }\n\n    function beaconProxyController() internal view returns (IBeaconProxyController) {\n        return IBeaconProxyController(getAddress(Contracts.BEACON_PROXY_CONTROLLER));\n    }\n\n    function currencyController() internal view returns (ICurrencyController) {\n        return ICurrencyController(getAddress(Contracts.CURRENCY_CONTROLLER));\n    }\n\n    function genesisValueVault() internal view returns (IGenesisValueVault) {\n        return IGenesisValueVault(getAddress(Contracts.GENESIS_VALUE_VAULT));\n    }\n\n    function lendingMarketController() internal view returns (ILendingMarketController) {\n        return ILendingMarketController(getAddress(Contracts.LENDING_MARKET_CONTROLLER));\n    }\n\n    function reserveFund() internal view returns (IReserveFund) {\n        return IReserveFund(getAddress(Contracts.RESERVE_FUND));\n    }\n\n    function tokenVault() internal view returns (ITokenVault) {\n        return ITokenVault(getAddress(Contracts.TOKEN_VAULT));\n    }\n}\n"
      },
      "contracts/protocol/libraries/Constants.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\nlibrary Constants {\n    /// @dev Used for price digits in the basis (10000 -> 1)\n    uint256 internal constant PRICE_DIGIT = 10000;\n\n    /// @dev Used for percentage digits in the basis (10000 -> 100%)\n    uint256 internal constant PCT_DIGIT = 10000;\n\n    /// @dev Used for seconds in year (60 * 60 * 24 * 365)\n    uint256 internal constant SECONDS_IN_YEAR = 31536000;\n\n    /// @dev Used for maximum order count per currency\n    uint256 internal constant MAXIMUM_ORDER_COUNT = 20;\n}\n"
      },
      "contracts/protocol/libraries/Contracts.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\nlibrary Contracts {\n    bytes32 internal constant BEACON_PROXY_CONTROLLER = \"BeaconProxyController\";\n    bytes32 internal constant CURRENCY_CONTROLLER = \"CurrencyController\";\n    bytes32 internal constant GENESIS_VALUE_VAULT = \"GenesisValueVault\";\n    bytes32 internal constant LENDING_MARKET_CONTROLLER = \"LendingMarketController\";\n    bytes32 internal constant RESERVE_FUND = \"ReserveFund\";\n    bytes32 internal constant TOKEN_VAULT = \"TokenVault\";\n}\n\nlibrary BeaconContracts {\n    bytes32 internal constant FUTURE_VALUE_VAULT = \"FutureValueVault\";\n    bytes32 internal constant LENDING_MARKET = \"LendingMarket\";\n    bytes32 internal constant ZC_TOKEN = \"ZCToken\";\n}\n"
      },
      "contracts/protocol/libraries/logics/DepositManagementLogic.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\n// dependencies\nimport {EnumerableSet} from \"../../../dependencies/openzeppelin/utils/structs/EnumerableSet.sol\";\n// interfaces\nimport {ILendingMarketController} from \"../../interfaces/ILendingMarketController.sol\";\n// libraries\nimport {AddressResolverLib} from \"../AddressResolverLib.sol\";\nimport {TransferHelper} from \"../TransferHelper.sol\";\nimport {Constants} from \"../Constants.sol\";\nimport {RoundingUint256} from \"../math/RoundingUint256.sol\";\n// storages\nimport {TokenVaultStorage as Storage} from \"../../storages/TokenVaultStorage.sol\";\n\nlibrary DepositManagementLogic {\n    using EnumerableSet for EnumerableSet.Bytes32Set;\n    using RoundingUint256 for uint256;\n\n    error NotEnoughDeposit(bytes32 ccy);\n    error ProtocolIsInsolvent(bytes32 ccy);\n\n    struct CalculatedFundVars {\n        uint256 plusDepositAmountInAdditionalFundsCcy;\n        uint256 minusDepositAmountInAdditionalFundsCcy;\n        uint256 workingLendOrdersAmount;\n        uint256 collateralAmount;\n        uint256 lentAmount;\n        uint256 workingBorrowOrdersAmount;\n        uint256 debtAmount;\n        uint256 borrowedAmount;\n    }\n\n    function isCovered(\n        address _user,\n        bytes32 _orderCcy\n    ) public view returns (bool isEnoughCollateral, bool isEnoughDepositInOrderCcy) {\n        ILendingMarketController.AdditionalFunds memory _funds;\n        _funds.ccy = _orderCcy;\n\n        (\n            uint256 totalCollateral,\n            uint256 totalUsedCollateral,\n            ,\n            bool isInsufficientDepositAmount\n        ) = _calculateCollateral(_user, _funds);\n\n        isEnoughDepositInOrderCcy = !isInsufficientDepositAmount;\n        isEnoughCollateral =\n            totalUsedCollateral == 0 ||\n            (totalCollateral * Constants.PCT_DIGIT >=\n                totalUsedCollateral * Storage.slot().liquidationThresholdRate);\n    }\n\n    function getUsedCurrencies(address _user) public view returns (bytes32[] memory) {\n        return Storage.slot().usedCurrencies[_user].values();\n    }\n\n    function getDepositAmount(address _user, bytes32 _ccy) public view returns (uint256) {\n        ILendingMarketController.CalculatedFunds memory funds = AddressResolverLib\n            .lendingMarketController()\n            .calculateFunds(_ccy, _user, Storage.slot().liquidationThresholdRate);\n\n        return\n            Storage.slot().depositAmounts[_user][_ccy] +\n            funds.borrowedAmount -\n            funds.lentAmount -\n            funds.workingLendOrdersAmount;\n    }\n\n    function getTotalCollateralAmount(\n        address _user\n    )\n        public\n        view\n        returns (uint256 totalCollateral, uint256 totalUsedCollateral, uint256 totalDeposit)\n    {\n        ILendingMarketController.AdditionalFunds memory _funds;\n        (totalCollateral, totalUsedCollateral, totalDeposit, ) = _calculateCollateral(\n            _user,\n            _funds\n        );\n    }\n\n    function getCollateralAmount(\n        address _user,\n        bytes32 _ccy\n    )\n        public\n        view\n        returns (uint256 totalCollateral, uint256 totalUsedCollateral, uint256 totalDeposit)\n    {\n        ILendingMarketController.CalculatedFunds memory funds = AddressResolverLib\n            .lendingMarketController()\n            .calculateFunds(_ccy, _user, Storage.slot().liquidationThresholdRate);\n\n        uint256 plusDeposit = Storage.slot().depositAmounts[_user][_ccy] + funds.borrowedAmount;\n        uint256 minusDeposit = funds.workingLendOrdersAmount + funds.lentAmount;\n        uint256 plusCollateral = plusDeposit + funds.collateralAmount;\n\n        totalCollateral = plusCollateral >= minusDeposit ? plusCollateral - minusDeposit : 0;\n        totalUsedCollateral = funds.workingBorrowOrdersAmount + funds.debtAmount;\n        totalDeposit = plusDeposit >= minusDeposit ? plusDeposit - minusDeposit : 0;\n    }\n\n    function getCoverage(address _user) external view returns (uint256 coverage) {\n        ILendingMarketController.AdditionalFunds memory _emptyAdditionalFunds;\n        (coverage, ) = calculateCoverage(_user, _emptyAdditionalFunds);\n    }\n\n    function getTotalUnusedCollateralAmount(address _user) public view returns (uint256) {\n        (uint256 totalCollateral, uint256 totalUsedCollateral, ) = getTotalCollateralAmount(_user);\n\n        return totalCollateral > totalUsedCollateral ? totalCollateral - totalUsedCollateral : 0;\n    }\n\n    function getBorrowableAmount(address _user, bytes32 _ccy) external view returns (uint256) {\n        uint256[] memory amounts = new uint256[](2);\n        (amounts[0], amounts[1], ) = getTotalCollateralAmount(_user);\n        amounts = AddressResolverLib.currencyController().convertFromBaseCurrency(_ccy, amounts);\n\n        uint256 totalCollateralAmount = amounts[0];\n        uint256 totalUsedCollateral = amounts[1];\n        uint256 liquidationThresholdRate = Storage.slot().liquidationThresholdRate;\n\n        ILendingMarketController.CalculatedFunds memory funds = AddressResolverLib\n            .lendingMarketController()\n            .calculateFunds(_ccy, _user, liquidationThresholdRate);\n\n        uint256 unusedCollateralAmount = funds.claimableAmount > funds.collateralAmount\n            ? funds.claimableAmount - funds.collateralAmount\n            : 0;\n\n        uint256 borrowableAmount = ((totalCollateralAmount + unusedCollateralAmount) *\n            Constants.PCT_DIGIT).div(liquidationThresholdRate);\n\n        return borrowableAmount > totalUsedCollateral ? borrowableAmount - totalUsedCollateral : 0;\n    }\n\n    function calculateCoverage(\n        address _user,\n        ILendingMarketController.AdditionalFunds memory _additionalFunds\n    ) public view returns (uint256 coverage, bool isInsufficientDepositAmount) {\n        uint256 totalCollateral;\n        uint256 totalUsedCollateral;\n\n        (\n            totalCollateral,\n            totalUsedCollateral,\n            ,\n            isInsufficientDepositAmount\n        ) = _calculateCollateral(_user, _additionalFunds);\n\n        if (totalCollateral == 0) {\n            coverage = totalUsedCollateral == 0 ? 0 : type(uint256).max;\n        } else {\n            coverage = (totalUsedCollateral * Constants.PCT_DIGIT) / totalCollateral;\n        }\n    }\n\n    function _calculateCollateral(\n        address _user,\n        ILendingMarketController.AdditionalFunds memory _funds\n    )\n        internal\n        view\n        returns (\n            uint256 totalCollateral,\n            uint256 totalUsedCollateral,\n            uint256 totalDeposit,\n            bool isInsufficientDepositAmount\n        )\n    {\n        CalculatedFundVars memory vars;\n\n        ILendingMarketController.CalculatedTotalFunds memory funds = AddressResolverLib\n            .lendingMarketController()\n            .calculateTotalFundsInBaseCurrency(\n                _user,\n                _funds,\n                Storage.slot().liquidationThresholdRate\n            );\n\n        vars.plusDepositAmountInAdditionalFundsCcy = funds.plusDepositAmountInAdditionalFundsCcy;\n        vars.minusDepositAmountInAdditionalFundsCcy = funds.minusDepositAmountInAdditionalFundsCcy;\n        vars.workingLendOrdersAmount = funds.workingLendOrdersAmount;\n        vars.collateralAmount = funds.collateralAmount;\n        vars.lentAmount = funds.lentAmount;\n        vars.workingBorrowOrdersAmount = funds.workingBorrowOrdersAmount;\n        vars.debtAmount = funds.debtAmount;\n        vars.borrowedAmount = funds.borrowedAmount;\n\n        // Check if the user has enough deposit amount in the selected currency.\n        if (\n            vars.plusDepositAmountInAdditionalFundsCcy +\n                Storage.slot().depositAmounts[_user][_funds.ccy] <\n            vars.minusDepositAmountInAdditionalFundsCcy\n        ) {\n            isInsufficientDepositAmount = true;\n        }\n\n        uint256 totalInternalDepositAmount = _getTotalInternalDepositAmountInBaseCurrency(_user);\n\n        uint256 plusDeposit = totalInternalDepositAmount + vars.borrowedAmount;\n        uint256 minusDeposit = vars.workingLendOrdersAmount + vars.lentAmount;\n        uint256 plusCollateral = plusDeposit + vars.collateralAmount;\n\n        totalCollateral = plusCollateral >= minusDeposit ? plusCollateral - minusDeposit : 0;\n        totalUsedCollateral = vars.workingBorrowOrdersAmount + vars.debtAmount;\n        totalDeposit = plusDeposit >= minusDeposit ? plusDeposit - minusDeposit : 0;\n    }\n\n    function getWithdrawableCollateral(address _user) public view returns (uint256) {\n        (\n            uint256 totalCollateral,\n            uint256 totalUsedCollateral,\n            uint256 totalDeposit\n        ) = getTotalCollateralAmount(_user);\n\n        if (totalUsedCollateral == 0) {\n            return totalDeposit;\n        } else if (\n            totalCollateral * Constants.PCT_DIGIT >\n            totalUsedCollateral * Storage.slot().liquidationThresholdRate\n        ) {\n            // NOTE: The formula is:\n            // maxWithdraw = totalCollateral - (totalUsedCollateral * liquidationThresholdRate)\n            uint256 maxWithdraw = (totalCollateral *\n                Constants.PCT_DIGIT -\n                totalUsedCollateral *\n                Storage.slot().liquidationThresholdRate).div(Constants.PCT_DIGIT);\n\n            return maxWithdraw >= totalDeposit ? totalDeposit : maxWithdraw;\n        } else {\n            return 0;\n        }\n    }\n\n    function getWithdrawableCollateral(\n        bytes32 _ccy,\n        address _user\n    ) public view returns (uint256 withdrawableAmount) {\n        uint256 depositAmount = getDepositAmount(_user, _ccy);\n        if (Storage.slot().collateralCurrencies.contains(_ccy)) {\n            uint256 maxWithdrawInBaseCurrency = getWithdrawableCollateral(_user);\n            uint256 maxWithdraw = AddressResolverLib.currencyController().convertFromBaseCurrency(\n                _ccy,\n                maxWithdrawInBaseCurrency\n            );\n\n            withdrawableAmount = depositAmount >= maxWithdraw ? maxWithdraw : depositAmount;\n        } else {\n            withdrawableAmount = depositAmount;\n        }\n    }\n\n    function addDepositAmount(address _user, bytes32 _ccy, uint256 _amount) public {\n        Storage.slot().depositAmounts[_user][_ccy] += _amount;\n        Storage.slot().usedCurrencies[_user].add(_ccy);\n    }\n\n    function removeDepositAmount(address _user, bytes32 _ccy, uint256 _amount) public {\n        if (Storage.slot().depositAmounts[_user][_ccy] < _amount) {\n            revert NotEnoughDeposit({ccy: _ccy});\n        }\n\n        Storage.slot().depositAmounts[_user][_ccy] -= _amount;\n    }\n\n    function executeForcedReset(\n        address _user,\n        bytes32 _ccy\n    ) external returns (uint256 removedAmount) {\n        removedAmount = Storage.slot().depositAmounts[_user][_ccy];\n        Storage.slot().depositAmounts[_user][_ccy] = 0;\n\n        Storage.slot().usedCurrencies[_user].remove(_ccy);\n    }\n\n    function deposit(address _caller, bytes32 _ccy, uint256 _amount, address _onBehalfOf) public {\n        TransferHelper.depositAssets(\n            Storage.slot().tokenAddresses[_ccy],\n            _caller,\n            address(this),\n            _amount\n        );\n\n        addDepositAmount(_onBehalfOf, _ccy, _amount);\n        Storage.slot().totalDepositAmount[_ccy] += _amount;\n    }\n\n    function withdraw(\n        address _user,\n        bytes32 _ccy,\n        uint256 _amount\n    ) public returns (uint256 withdrawableAmount) {\n        withdrawableAmount = getWithdrawableCollateral(_ccy, _user);\n        withdrawableAmount = _amount > withdrawableAmount ? withdrawableAmount : _amount;\n\n        if (Storage.slot().totalDepositAmount[_ccy] < withdrawableAmount) {\n            revert ProtocolIsInsolvent({ccy: _ccy});\n        }\n\n        Storage.slot().totalDepositAmount[_ccy] -= withdrawableAmount;\n        removeDepositAmount(_user, _ccy, withdrawableAmount);\n\n        TransferHelper.withdrawAssets(\n            Storage.slot().tokenAddresses[_ccy],\n            _user,\n            withdrawableAmount\n        );\n\n        return withdrawableAmount;\n    }\n\n    function getLiquidationAmount(\n        address _user,\n        bytes32 _liquidationCcy,\n        uint256 _liquidationAmountMaximum\n    ) public view returns (uint256 liquidationAmount, uint256 protocolFee, uint256 liquidatorFee) {\n        (\n            uint256 totalCollateralInBaseCcy,\n            uint256 totalUsedCollateralInBaseCcy,\n\n        ) = getTotalCollateralAmount(_user);\n\n        if (totalUsedCollateralInBaseCcy == 0) {\n            return (0, 0, 0);\n        }\n\n        (uint256 collateralAmount, , ) = getCollateralAmount(_user, _liquidationCcy);\n\n        if (collateralAmount == 0) {\n            return (0, 0, 0);\n        }\n\n        uint256 liquidationAmountInBaseCcy = 0;\n        uint256 coveredRatio = (totalCollateralInBaseCcy * Constants.PCT_DIGIT).div(\n            totalUsedCollateralInBaseCcy\n        );\n\n        if (coveredRatio < Storage.slot().fullLiquidationThresholdRate) {\n            liquidationAmountInBaseCcy = totalUsedCollateralInBaseCcy;\n        } else if (coveredRatio < Storage.slot().liquidationThresholdRate) {\n            liquidationAmountInBaseCcy = totalUsedCollateralInBaseCcy.div(2);\n        }\n\n        uint256[] memory amountsInBaseCcy = new uint256[](2);\n        amountsInBaseCcy[0] = liquidationAmountInBaseCcy;\n        amountsInBaseCcy[1] = totalCollateralInBaseCcy;\n\n        uint256[] memory amounts = AddressResolverLib.currencyController().convertFromBaseCurrency(\n            _liquidationCcy,\n            amountsInBaseCcy\n        );\n\n        liquidationAmount = amounts[0];\n        uint256 totalCollateralAmount = amounts[1];\n\n        if (liquidationAmount > _liquidationAmountMaximum) {\n            liquidationAmount = _liquidationAmountMaximum;\n        }\n\n        (protocolFee, liquidatorFee) = calculateLiquidationFees(liquidationAmount);\n\n        uint256 liquidationTotalAmount = liquidationAmount + protocolFee + liquidatorFee;\n\n        // NOTE: If `totalCollateralAmount > collateralAmount` is true, it means that a user has collateral in other currencies\n        // In this case, this liquidation is not covered by the reserve fund.\n        // Therefore, we need to keep the total liquidation amount within the maximum amount.\n        if (liquidationTotalAmount > collateralAmount && totalCollateralAmount > collateralAmount) {\n            liquidationTotalAmount = collateralAmount;\n            uint256 liquidatorFeeRate = Storage.slot().liquidatorFeeRate;\n            uint256 liquidationProtocolFeeRate = Storage.slot().liquidationProtocolFeeRate;\n\n            protocolFee = (liquidationTotalAmount * liquidationProtocolFeeRate).div(\n                Constants.PCT_DIGIT + liquidatorFeeRate + liquidationProtocolFeeRate\n            );\n            liquidatorFee = (liquidationTotalAmount * liquidatorFeeRate).div(\n                Constants.PCT_DIGIT + liquidatorFeeRate + liquidationProtocolFeeRate\n            );\n            liquidationAmount = liquidationTotalAmount - protocolFee - liquidatorFee;\n        }\n    }\n\n    function calculateLiquidationFees(\n        uint256 _amount\n    ) public view returns (uint256 protocolFee, uint256 liquidatorFee) {\n        protocolFee = (_amount * Storage.slot().liquidationProtocolFeeRate).div(\n            Constants.PCT_DIGIT\n        );\n        liquidatorFee = (_amount * Storage.slot().liquidatorFeeRate).div(Constants.PCT_DIGIT);\n    }\n\n    function transferFrom(\n        bytes32 _ccy,\n        address _from,\n        address _to,\n        uint256 _amount\n    ) external returns (uint256 untransferredAmount) {\n        uint256 depositAmount = getDepositAmount(_from, _ccy);\n        uint256 amount = depositAmount >= _amount ? _amount : depositAmount;\n        untransferredAmount = _amount - amount;\n\n        removeDepositAmount(_from, _ccy, amount);\n        addDepositAmount(_to, _ccy, amount);\n    }\n\n    function cleanUpUsedCurrencies(address _user, bytes32 _ccy) external {\n        if (Storage.slot().depositAmounts[_user][_ccy] == 0) {\n            Storage.slot().usedCurrencies[_user].remove(_ccy);\n        }\n    }\n\n    /**\n     * @notice Gets the total of amount deposited in the user's collateral of all currencies\n     *  in this contract by converting it to ETH.\n     * @param _user Address of collateral user\n     * @return totalDepositAmount The total deposited amount in the base currency\n     */\n    function _getTotalInternalDepositAmountInBaseCurrency(\n        address _user\n    ) internal view returns (uint256 totalDepositAmount) {\n        EnumerableSet.Bytes32Set storage currencies = Storage.slot().usedCurrencies[_user];\n        uint256 length = currencies.length();\n\n        for (uint256 i; i < length; i++) {\n            bytes32 ccy = currencies.at(i);\n            if (Storage.slot().collateralCurrencies.contains(ccy)) {\n                uint256 depositAmount = Storage.slot().depositAmounts[_user][ccy];\n                totalDepositAmount += AddressResolverLib.currencyController().convertToBaseCurrency(\n                    ccy,\n                    depositAmount\n                );\n            }\n        }\n\n        return totalDepositAmount;\n    }\n}\n"
      },
      "contracts/protocol/libraries/math/RoundingUint256.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\nlibrary RoundingUint256 {\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\n        require(b > 0);\n\n        if ((a * 10) / b - (a / b) * 10 < 5) {\n            return a / b;\n        } else {\n            return (a / b) + 1;\n        }\n    }\n}\n"
      },
      "contracts/protocol/libraries/TransferHelper.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\nimport {INativeToken} from \"../interfaces/INativeToken.sol\";\nimport {TransferHelperStorage as Storage} from \"../storages/libraries/TransferHelperStorage.sol\";\n\nlibrary TransferHelper {\n    function initialize(address _nativeToken) internal {\n        require(Storage.slot().nativeToken == address(0), \"TransferHelper: Already initialized\");\n        Storage.slot().nativeToken = _nativeToken;\n    }\n\n    function nativeToken() internal view returns (address) {\n        return Storage.slot().nativeToken;\n    }\n\n    function isNative(address _token) internal view returns (bool) {\n        return _token == Storage.slot().nativeToken;\n    }\n\n    function depositAssets(\n        address _token,\n        address _payer,\n        address _receiver,\n        uint256 _amount\n    ) internal {\n        if (address(_token) == Storage.slot().nativeToken) {\n            convertToWrappedToken(_receiver, _amount);\n        } else {\n            safeTransferFrom(_token, _payer, _receiver, _amount);\n        }\n    }\n\n    function withdrawAssets(address _token, address _receiver, uint256 _amount) internal {\n        if (address(_token) == Storage.slot().nativeToken) {\n            convertFromWrappedToken(_receiver, _amount);\n        } else {\n            safeTransfer(_token, _receiver, _amount);\n        }\n    }\n\n    function convertToWrappedToken(address _receiver, uint256 _amount) internal {\n        require(address(this).balance >= _amount, \"TransferHelper: Insufficient balance\");\n\n        INativeToken(Storage.slot().nativeToken).deposit{value: _amount}();\n        safeTransfer(Storage.slot().nativeToken, _receiver, _amount);\n    }\n\n    function convertFromWrappedToken(address _receiver, uint256 _amount) internal {\n        uint256 balance = INativeToken(Storage.slot().nativeToken).balanceOf(address(this));\n        require(balance >= _amount, \"TransferHelper: Insufficient balance\");\n\n        if (balance > 0) {\n            INativeToken(Storage.slot().nativeToken).withdraw(_amount);\n            safeTransferETH(_receiver, _amount);\n        }\n    }\n\n    /// @dev Transfer helper from UniswapV2 Router\n    function safeApprove(address token, address to, uint256 value) internal {\n        // bytes4(keccak256(bytes('approve(address,uint256)')));\n        (bool success, bytes memory data) = token.call(\n            abi.encodeWithSelector(0x095ea7b3, to, value)\n        );\n        require(\n            success && (data.length == 0 || abi.decode(data, (bool))),\n            \"TransferHelper: APPROVE_FAILED\"\n        );\n    }\n\n    /**\n     * There are many non-compliant ERC20 tokens... this can handle most, adapted from UniSwap V2\n     * Im trying to make it a habit to put external calls last (reentrancy)\n     * You can put this in an internal function if you like.\n     */\n    function safeTransfer(address token, address to, uint256 amount) internal {\n        // solium-disable-next-line security/no-low-level-calls\n        (bool success, bytes memory data) = token.call(\n            // 0xa9059cbb = bytes4(keccak256(\"transfer(address,uint256)\"))\n            abi.encodeWithSelector(0xa9059cbb, to, amount)\n        );\n        require(\n            success && (data.length == 0 || abi.decode(data, (bool))),\n            \"TransferHelper: TRANSFER_FAILED\"\n        ); // ERC20 Transfer failed\n    }\n\n    function safeTransferFrom(address token, address from, address to, uint256 value) internal {\n        (bool success, bytes memory data) = token.call(\n            abi.encodeWithSelector(0x23b872dd, from, to, value)\n        );\n        require(\n            success && (data.length == 0 || abi.decode(data, (bool))),\n            \"TransferHelper: TRANSFER_FROM_FAILED\"\n        );\n    }\n\n    function safeTransferETH(address to, uint256 value) internal {\n        (bool success, ) = to.call{value: value}(new bytes(0));\n        require(success, \"TransferHelper: ETH_TRANSFER_FAILED\");\n    }\n}\n"
      },
      "contracts/protocol/storages/CurrencyControllerStorage.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\nimport \"../../dependencies/chainlink/AggregatorV3Interface.sol\";\nimport \"../../dependencies/openzeppelin/utils/structs/EnumerableSet.sol\";\n\nstruct PriceFeed {\n    AggregatorV3Interface[] instances;\n    uint256[] heartbeats;\n}\n\nlibrary CurrencyControllerStorage {\n    using EnumerableSet for EnumerableSet.Bytes32Set;\n\n    bytes32 internal constant STORAGE_SLOT =\n        bytes32(uint256(keccak256(\"sf.storage.currencyController\")) - 1);\n\n    struct Storage {\n        // Protocol currencies\n        EnumerableSet.Bytes32Set currencies;\n        mapping(bytes32 ccy => uint256 haircut) haircuts;\n        // Total cached decimals of the price feeds\n        mapping(bytes32 ccy => uint8 decimals) decimalsCaches;\n        mapping(bytes32 ccy => PriceFeed priceFeed) priceFeeds;\n    }\n\n    function slot() internal pure returns (Storage storage r) {\n        bytes32 _slot = STORAGE_SLOT;\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := _slot\n        }\n    }\n}\n"
      },
      "contracts/protocol/storages/GenesisValueVaultStorage.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\nstruct MaturityUnitPrice {\n    uint256 unitPrice;\n    uint256 compoundFactor;\n    uint256 next;\n    uint256 prev;\n}\n\nstruct AutoRollLog {\n    uint256 unitPrice;\n    uint256 lendingCompoundFactor;\n    uint256 borrowingCompoundFactor;\n    uint256 next;\n    uint256 prev;\n}\n\nlibrary GenesisValueVaultStorage {\n    bytes32 internal constant STORAGE_SLOT =\n        bytes32(uint256(keccak256(\"sf.storage.genesisValueVault\")) - 1);\n\n    struct Storage {\n        mapping(bytes32 ccy => bool isInitialized) isInitialized;\n        mapping(bytes32 ccy => uint256 compoundFactor) initialCompoundFactors;\n        mapping(bytes32 ccy => uint256 compoundFactor) lendingCompoundFactors;\n        mapping(bytes32 ccy => uint256 compoundFactor) borrowingCompoundFactors;\n        mapping(bytes32 ccy => uint256 maturity) currentMaturity;\n        mapping(bytes32 ccy => uint8 decimals) decimals;\n        mapping(bytes32 ccy => mapping(address user => int256 balance)) balances;\n        mapping(bytes32 ccy => uint256 amount) totalLendingSupplies;\n        mapping(bytes32 ccy => uint256 amount) totalBorrowingSupplies;\n        // Total amount supplied per maturity\n        mapping(bytes32 ccy => mapping(uint256 maturity => int256 balance)) maturityBalances;\n        mapping(bytes32 ccy => mapping(uint256 maturity => AutoRollLog log)) autoRollLogs;\n        // Maturity when the user receives the balance on the target currency\n        mapping(bytes32 ccy => mapping(address user => uint256 maturity)) userMaturities;\n        mapping(bytes32 ccy => uint256 balance) totalLockedBalances;\n    }\n\n    function slot() internal pure returns (Storage storage r) {\n        bytes32 _slot = STORAGE_SLOT;\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := _slot\n        }\n    }\n}\n"
      },
      "contracts/protocol/storages/LendingMarketControllerStorage.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\nimport \"../../dependencies/openzeppelin/utils/structs/EnumerableSet.sol\";\n\nstruct ObservationPeriodLog {\n    uint256 totalAmount;\n    uint256 totalFutureValue;\n}\n\nstruct TerminationCurrencyCache {\n    int256 price;\n    uint8 decimals;\n}\n\nstruct ZCTokenInfo {\n    bytes32 ccy;\n    uint256 maturity;\n}\n\nlibrary LendingMarketControllerStorage {\n    using EnumerableSet for EnumerableSet.Bytes32Set;\n    using EnumerableSet for EnumerableSet.UintSet;\n\n    bytes32 internal constant STORAGE_SLOT =\n        bytes32(uint256(keccak256(\"sf.storage.lendingMarketController\")) - 1);\n\n    struct Storage {\n        uint256 marketBasePeriod;\n        uint256 terminationDate;\n        mapping(bytes32 ccy => TerminationCurrencyCache currency) terminationCurrencyCaches;\n        mapping(bytes32 ccy => uint256 ratio) terminationCollateralRatios;\n        mapping(bytes32 ccy => uint8[] orderBookIds) orderBookIdLists;\n        mapping(bytes32 ccy => address lendingMarket) lendingMarkets;\n        mapping(bytes32 ccy => address futureValueVault) futureValueVaults;\n        mapping(bytes32 ccy => uint256 unitPrice) minDebtUnitPrices;\n        mapping(bytes32 ccy => uint256 genesisDate) genesisDates;\n        mapping(bytes32 ccy => mapping(uint256 maturity => uint256 amount)) pendingOrderAmounts;\n        // Order book id history to get order book id from maturity\n        mapping(bytes32 ccy => mapping(uint256 maturity => uint8 orderBookIds)) maturityOrderBookIds;\n        // List of maturity that the user has open orders or positions\n        mapping(bytes32 ccy => mapping(address user => EnumerableSet.UintSet maturities)) usedMaturities;\n        // Observation period logs that is used for auto-rolls\n        mapping(bytes32 ccy => mapping(uint256 maturity => ObservationPeriodLog log)) observationPeriodLogs;\n        // List of currency that the user has open orders or positions\n        mapping(address user => EnumerableSet.Bytes32Set currency) usedCurrencies;\n        mapping(address user => bool isRedeemed) isRedeemed;\n        mapping(bytes32 ccy => mapping(uint256 maturity => address token)) zcTokens;\n        mapping(address token => ZCTokenInfo) zcTokenInfo;\n    }\n\n    function slot() internal pure returns (Storage storage r) {\n        bytes32 _slot = STORAGE_SLOT;\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := _slot\n        }\n    }\n}\n"
      },
      "contracts/protocol/storages/libraries/TransferHelperStorage.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\nlibrary TransferHelperStorage {\n    bytes32 internal constant STORAGE_SLOT =\n        bytes32(uint256(keccak256(\"sf.storage.transferHelper\")) - 1);\n\n    struct Storage {\n        address nativeToken;\n    }\n\n    function slot() internal pure returns (Storage storage r) {\n        bytes32 _slot = STORAGE_SLOT;\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := _slot\n        }\n    }\n}\n"
      },
      "contracts/protocol/storages/mixins/MixinAddressResolverStorage.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\nimport {IAddressResolver} from \"../../interfaces/IAddressResolver.sol\";\n\nlibrary MixinAddressResolverStorage {\n    bytes32 internal constant STORAGE_SLOT =\n        bytes32(uint256(keccak256(\"sf.storage.mixinAddressResolver\")) - 1);\n\n    struct Storage {\n        IAddressResolver resolver;\n        mapping(bytes32 contractName => address contractAddress) addressCache;\n    }\n\n    function slot() internal pure returns (Storage storage r) {\n        bytes32 _slot = STORAGE_SLOT;\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := _slot\n        }\n    }\n}\n"
      },
      "contracts/protocol/storages/TokenVaultStorage.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\nimport {EnumerableSet} from \"../../dependencies/openzeppelin/utils/structs/EnumerableSet.sol\";\n\nlibrary TokenVaultStorage {\n    using EnumerableSet for EnumerableSet.Bytes32Set;\n\n    bytes32 internal constant STORAGE_SLOT =\n        bytes32(uint256(keccak256(\"sf.storage.tokenVault\")) - 1);\n\n    struct Storage {\n        // Liquidation threshold rate (in basis point)\n        uint256 liquidationThresholdRate;\n        // Liquidation fee rate received by protocol (in basis point)\n        uint256 liquidationProtocolFeeRate;\n        // Liquidation fee rate received by liquidators (in basis point)\n        uint256 liquidatorFeeRate;\n        // Currencies accepted as collateral\n        EnumerableSet.Bytes32Set collateralCurrencies;\n        mapping(bytes32 ccy => address tokenAddress) tokenAddresses;\n        // List of currency that the user has deposit amounts\n        mapping(address user => EnumerableSet.Bytes32Set currency) usedCurrencies;\n        mapping(bytes32 ccy => uint256 totalDepositAmount) totalDepositAmount;\n        mapping(address user => mapping(bytes32 currency => uint256 depositAmount)) depositAmounts;\n        // Full liquidation threshold rate (in basis point)\n        uint256 fullLiquidationThresholdRate;\n    }\n\n    function slot() internal pure returns (Storage storage r) {\n        bytes32 _slot = STORAGE_SLOT;\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := _slot\n        }\n    }\n}\n"
      },
      "contracts/protocol/types/ProtocolTypes.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\n/**\n * @dev ProtocolTypes is a base-level contract that holds common Secured Finance protocol types\n * @author Secured Finance\n */\nlibrary ProtocolTypes {\n    enum Side {\n        LEND,\n        BORROW\n    }\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "metadata": {
        "useLiteralContent": true
      },
      "libraries": {}
    }
  }}