creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "@openzeppelin/contracts/token/ERC20/ERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n    mapping(address => uint256) private _balances;\n\n    mapping(address => mapping(address => uint256)) private _allowances;\n\n    uint256 private _totalSupply;\n\n    string private _name;\n    string private _symbol;\n\n    /**\n     * @dev Sets the values for {name} and {symbol}.\n     *\n     * The default value of {decimals} is 18. To select a different value for\n     * {decimals} you should overload it.\n     *\n     * All two of these values are immutable: they can only be set once during\n     * construction.\n     */\n    constructor(string memory name_, string memory symbol_) {\n        _name = name_;\n        _symbol = symbol_;\n    }\n\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() public view virtual override returns (string memory) {\n        return _name;\n    }\n\n    /**\n     * @dev Returns the symbol of the token, usually a shorter version of the\n     * name.\n     */\n    function symbol() public view virtual override returns (string memory) {\n        return _symbol;\n    }\n\n    /**\n     * @dev Returns the number of decimals used to get its user representation.\n     * For example, if `decimals` equals `2`, a balance of `505` tokens should\n     * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n     *\n     * Tokens usually opt for a value of 18, imitating the relationship between\n     * Ether and Wei. This is the value {ERC20} uses, unless this function is\n     * overridden;\n     *\n     * NOTE: This information is only used for _display_ purposes: it in\n     * no way affects any of the arithmetic of the contract, including\n     * {IERC20-balanceOf} and {IERC20-transfer}.\n     */\n    function decimals() public view virtual override returns (uint8) {\n        return 18;\n    }\n\n    /**\n     * @dev See {IERC20-totalSupply}.\n     */\n    function totalSupply() public view virtual override returns (uint256) {\n        return _totalSupply;\n    }\n\n    /**\n     * @dev See {IERC20-balanceOf}.\n     */\n    function balanceOf(address account) public view virtual override returns (uint256) {\n        return _balances[account];\n    }\n\n    /**\n     * @dev See {IERC20-transfer}.\n     *\n     * Requirements:\n     *\n     * - `recipient` cannot be the zero address.\n     * - the caller must have a balance of at least `amount`.\n     */\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\n        _transfer(_msgSender(), recipient, amount);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-allowance}.\n     */\n    function allowance(address owner, address spender) public view virtual override returns (uint256) {\n        return _allowances[owner][spender];\n    }\n\n    /**\n     * @dev See {IERC20-approve}.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\n        _approve(_msgSender(), spender, amount);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-transferFrom}.\n     *\n     * Emits an {Approval} event indicating the updated allowance. This is not\n     * required by the EIP. See the note at the beginning of {ERC20}.\n     *\n     * Requirements:\n     *\n     * - `sender` and `recipient` cannot be the zero address.\n     * - `sender` must have a balance of at least `amount`.\n     * - the caller must have allowance for ``sender``'s tokens of at least\n     * `amount`.\n     */\n    function transferFrom(\n        address sender,\n        address recipient,\n        uint256 amount\n    ) public virtual override returns (bool) {\n        _transfer(sender, recipient, amount);\n\n        uint256 currentAllowance = _allowances[sender][_msgSender()];\n        require(currentAllowance >= amount, \"ERC20: transfer amount exceeds allowance\");\n        unchecked {\n            _approve(sender, _msgSender(), currentAllowance - amount);\n        }\n\n        return true;\n    }\n\n    /**\n     * @dev Atomically increases the allowance granted to `spender` by the caller.\n     *\n     * This is an alternative to {approve} that can be used as a mitigation for\n     * problems described in {IERC20-approve}.\n     *\n     * Emits an {Approval} event indicating the updated allowance.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n        _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);\n        return true;\n    }\n\n    /**\n     * @dev Atomically decreases the allowance granted to `spender` by the caller.\n     *\n     * This is an alternative to {approve} that can be used as a mitigation for\n     * problems described in {IERC20-approve}.\n     *\n     * Emits an {Approval} event indicating the updated allowance.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `spender` must have allowance for the caller of at least\n     * `subtractedValue`.\n     */\n    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n        uint256 currentAllowance = _allowances[_msgSender()][spender];\n        require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n        unchecked {\n            _approve(_msgSender(), spender, currentAllowance - subtractedValue);\n        }\n\n        return true;\n    }\n\n    /**\n     * @dev Moves `amount` of tokens from `sender` to `recipient`.\n     *\n     * This internal function is equivalent to {transfer}, and can be used to\n     * e.g. implement automatic token fees, slashing mechanisms, etc.\n     *\n     * Emits a {Transfer} event.\n     *\n     * Requirements:\n     *\n     * - `sender` cannot be the zero address.\n     * - `recipient` cannot be the zero address.\n     * - `sender` must have a balance of at least `amount`.\n     */\n    function _transfer(\n        address sender,\n        address recipient,\n        uint256 amount\n    ) internal virtual {\n        require(sender != address(0), \"ERC20: transfer from the zero address\");\n        require(recipient != address(0), \"ERC20: transfer to the zero address\");\n\n        _beforeTokenTransfer(sender, recipient, amount);\n\n        uint256 senderBalance = _balances[sender];\n        require(senderBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n        unchecked {\n            _balances[sender] = senderBalance - amount;\n        }\n        _balances[recipient] += amount;\n\n        emit Transfer(sender, recipient, amount);\n\n        _afterTokenTransfer(sender, recipient, amount);\n    }\n\n    /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n     * the total supply.\n     *\n     * Emits a {Transfer} event with `from` set to the zero address.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     */\n    function _mint(address account, uint256 amount) internal virtual {\n        require(account != address(0), \"ERC20: mint to the zero address\");\n\n        _beforeTokenTransfer(address(0), account, amount);\n\n        _totalSupply += amount;\n        _balances[account] += amount;\n        emit Transfer(address(0), account, amount);\n\n        _afterTokenTransfer(address(0), account, amount);\n    }\n\n    /**\n     * @dev Destroys `amount` tokens from `account`, reducing the\n     * total supply.\n     *\n     * Emits a {Transfer} event with `to` set to the zero address.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     * - `account` must have at least `amount` tokens.\n     */\n    function _burn(address account, uint256 amount) internal virtual {\n        require(account != address(0), \"ERC20: burn from the zero address\");\n\n        _beforeTokenTransfer(account, address(0), amount);\n\n        uint256 accountBalance = _balances[account];\n        require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n        unchecked {\n            _balances[account] = accountBalance - amount;\n        }\n        _totalSupply -= amount;\n\n        emit Transfer(account, address(0), amount);\n\n        _afterTokenTransfer(account, address(0), amount);\n    }\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n     *\n     * This internal function is equivalent to `approve`, and can be used to\n     * e.g. set automatic allowances for certain subsystems, etc.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `owner` cannot be the zero address.\n     * - `spender` cannot be the zero address.\n     */\n    function _approve(\n        address owner,\n        address spender,\n        uint256 amount\n    ) internal virtual {\n        require(owner != address(0), \"ERC20: approve from the zero address\");\n        require(spender != address(0), \"ERC20: approve to the zero address\");\n\n        _allowances[owner][spender] = amount;\n        emit Approval(owner, spender, amount);\n    }\n\n    /**\n     * @dev Hook that is called before any transfer of tokens. This includes\n     * minting and burning.\n     *\n     * Calling conditions:\n     *\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n     * will be transferred to `to`.\n     * - when `from` is zero, `amount` tokens will be minted for `to`.\n     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n     * - `from` and `to` are never both zero.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _beforeTokenTransfer(\n        address from,\n        address to,\n        uint256 amount\n    ) internal virtual {}\n\n    /**\n     * @dev Hook that is called after any transfer of tokens. This includes\n     * minting and burning.\n     *\n     * Calling conditions:\n     *\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n     * has been transferred to `to`.\n     * - when `from` is zero, `amount` tokens have been minted for `to`.\n     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n     * - `from` and `to` are never both zero.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _afterTokenTransfer(\n        address from,\n        address to,\n        uint256 amount\n    ) internal virtual {}\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the symbol of the token.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the decimals places of the token.\n     */\n    function decimals() external view returns (uint8);\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (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 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 `recipient`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address recipient, 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 `sender` to `recipient` 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(\n        address sender,\n        address recipient,\n        uint256 amount\n    ) external returns (bool);\n\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"
      },
      "@openzeppelin/contracts/utils/Context.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n}\n"
      },
      "contracts/interfaces/IBaseSilo.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.13;\n\nimport \"./IShareToken.sol\";\nimport \"./IFlashLiquidationReceiver.sol\";\nimport \"./ISiloRepository.sol\";\n\ninterface IBaseSilo {\n    enum AssetStatus { Undefined, Active, Removed }\n\n    /// @dev Storage struct that holds all required data for a single token market\n    struct AssetStorage {\n        /// @dev Token that represents a share in totalDeposits of Silo\n        IShareToken collateralToken;\n        /// @dev Token that represents a share in collateralOnlyDeposits of Silo\n        IShareToken collateralOnlyToken;\n        /// @dev Token that represents a share in totalBorrowAmount of Silo\n        IShareToken debtToken;\n        /// @dev COLLATERAL: Amount of asset token that has been deposited to Silo with interest earned by depositors.\n        /// It also includes token amount that has been borrowed.\n        uint256 totalDeposits;\n        /// @dev COLLATERAL ONLY: Amount of asset token that has been deposited to Silo that can be ONLY used\n        /// as collateral. These deposits do NOT earn interest and CANNOT be borrowed.\n        uint256 collateralOnlyDeposits;\n        /// @dev DEBT: Amount of asset token that has been borrowed with accrued interest.\n        uint256 totalBorrowAmount;\n    }\n\n    /// @dev Storage struct that holds data related to fees and interest\n    struct AssetInterestData {\n        /// @dev Total amount of already harvested protocol fees\n        uint256 harvestedProtocolFees;\n        /// @dev Total amount (ever growing) of asset token that has been earned by the protocol from\n        /// generated interest.\n        uint256 protocolFees;\n        /// @dev Timestamp of the last time `interestRate` has been updated in storage.\n        uint64 interestRateTimestamp;\n        /// @dev True if asset was removed from the protocol. If so, deposit and borrow functions are disabled\n        /// for that asset\n        AssetStatus status;\n    }\n\n    /// @notice data that InterestModel needs for calculations\n    struct UtilizationData {\n        uint256 totalDeposits;\n        uint256 totalBorrowAmount;\n        /// @dev timestamp of last interest accrual\n        uint64 interestRateTimestamp;\n    }\n\n    /// @dev Shares names and symbols that are generated while asset initialization\n    struct AssetSharesMetadata {\n        /// @dev Name for the collateral shares token\n        string collateralName;\n        /// @dev Symbol for the collateral shares token\n        string collateralSymbol;\n        /// @dev Name for the collateral only (protected collateral) shares token\n        string protectedName;\n        /// @dev Symbol for the collateral only (protected collateral) shares token\n        string protectedSymbol;\n        /// @dev Name for the debt shares token\n        string debtName;\n        /// @dev Symbol for the debt shares token\n        string debtSymbol;\n    }\n\n    /// @notice Emitted when deposit is made\n    /// @param asset asset address that was deposited\n    /// @param depositor wallet address that deposited asset\n    /// @param amount amount of asset that was deposited\n    /// @param collateralOnly type of deposit, true if collateralOnly deposit was used\n    event Deposit(address indexed asset, address indexed depositor, uint256 amount, bool collateralOnly);\n\n    /// @notice Emitted when withdraw is made\n    /// @param asset asset address that was withdrawn\n    /// @param depositor wallet address that deposited asset\n    /// @param receiver wallet address that received asset\n    /// @param amount amount of asset that was withdrew\n    /// @param collateralOnly type of withdraw, true if collateralOnly deposit was used\n    event Withdraw(\n        address indexed asset,\n        address indexed depositor,\n        address indexed receiver,\n        uint256 amount,\n        bool collateralOnly\n    );\n\n    /// @notice Emitted on asset borrow\n    /// @param asset asset address that was borrowed\n    /// @param user wallet address that borrowed asset\n    /// @param amount amount of asset that was borrowed\n    event Borrow(address indexed asset, address indexed user, uint256 amount);\n\n    /// @notice Emitted on asset repay\n    /// @param asset asset address that was repaid\n    /// @param user wallet address that repaid asset\n    /// @param amount amount of asset that was repaid\n    event Repay(address indexed asset, address indexed user, uint256 amount);\n\n    /// @notice Emitted on user liquidation\n    /// @param asset asset address that was liquidated\n    /// @param user wallet address that was liquidated\n    /// @param shareAmountRepaid amount of collateral-share token that was repaid. This is collateral token representing\n    /// ownership of underlying deposit.\n    /// @param seizedCollateral amount of underlying token that was seized by liquidator\n    event Liquidate(address indexed asset, address indexed user, uint256 shareAmountRepaid, uint256 seizedCollateral);\n\n    /// @notice Emitted when the status for an asset is updated\n    /// @param asset asset address that was updated\n    /// @param status new asset status\n    event AssetStatusUpdate(address indexed asset, AssetStatus indexed status);\n\n    /// @return version of the silo contract\n    function VERSION() external returns (uint128); // solhint-disable-line func-name-mixedcase\n\n    /// @notice Synchronize current bridge assets with Silo\n    /// @dev This function needs to be called on Silo deployment to setup all assets for Silo. It needs to be\n    /// called every time a bridged asset is added or removed. When bridge asset is removed, depositing and borrowing\n    /// should be disabled during asset sync.\n    function syncBridgeAssets() external;\n\n    /// @notice Get Silo Repository contract address\n    /// @return Silo Repository contract address\n    function siloRepository() external view returns (ISiloRepository);\n\n    /// @notice Get asset storage data\n    /// @param _asset asset address\n    /// @return AssetStorage struct\n    function assetStorage(address _asset) external view returns (AssetStorage memory);\n\n    /// @notice Get asset interest data\n    /// @param _asset asset address\n    /// @return AssetInterestData struct\n    function interestData(address _asset) external view returns (AssetInterestData memory);\n\n    /// @dev helper method for InterestRateModel calculations\n    function utilizationData(address _asset) external view returns (UtilizationData memory data);\n\n    /// @notice Calculates solvency of an account\n    /// @param _user wallet address for which solvency is calculated\n    /// @return true if solvent, false otherwise\n    function isSolvent(address _user) external view returns (bool);\n\n    /// @notice Returns all initialized (synced) assets of Silo including current and removed bridge assets\n    /// @return assets array of initialized assets of Silo\n    function getAssets() external view returns (address[] memory assets);\n\n    /// @notice Returns all initialized (synced) assets of Silo including current and removed bridge assets\n    /// with corresponding state\n    /// @return assets array of initialized assets of Silo\n    /// @return assetsStorage array of assets state corresponding to `assets` array\n    function getAssetsWithState() external view returns (address[] memory assets, AssetStorage[] memory assetsStorage);\n\n    /// @notice Check if depositing an asset for given account is possible\n    /// @dev Depositing an asset that has been already borrowed (and vice versa) is disallowed\n    /// @param _asset asset we want to deposit\n    /// @param _depositor depositor address\n    /// @return true if asset can be deposited by depositor\n    function depositPossible(address _asset, address _depositor) external view returns (bool);\n\n    /// @notice Check if borrowing an asset for given account is possible\n    /// @dev Borrowing an asset that has been already deposited (and vice versa) is disallowed\n    /// @param _asset asset we want to deposit\n    /// @param _borrower borrower address\n    /// @return true if asset can be borrowed by borrower\n    function borrowPossible(address _asset, address _borrower) external view returns (bool);\n\n    /// @dev Amount of token that is available for borrowing\n    /// @param _asset asset to get liquidity for\n    /// @return Silo liquidity\n    function liquidity(address _asset) external view returns (uint256);\n}\n"
      },
      "contracts/interfaces/IERC20R.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n/// @dev This interface stands for \"ERC20 Reversed\",\n/// in the sense that the recipient of a transfer needs to approve the transfer amount first\ninterface IERC20R is IERC20 {\n    /// @dev Emitted when the allowance of a `_receiver` for an `_owner` is set by\n    /// a call to {changeReceiveApproval}. `value` is the new allowance.\n    /// @param _owner previous owner of the debt\n    /// @param _receiver wallet that received debt\n    /// @param _value amount of token transferred\n    event ReceiveApproval(address indexed _owner, address indexed _receiver, uint256 _value);\n\n    /// @dev Atomically decreases the receive allowance granted to `owner` by the caller.\n    /// This is an alternative to {receive approve} that can be used as a mitigation for problems\n    /// described in {IERC20-approve}.\n    /// Emits an {ReceiveApproval} event indicating the updated receive allowance.\n    /// @param _owner owner of debt token that is being allowed sending it to the caller\n    /// @param _subtractedValue amount of token to decrease allowance\n    function decreaseReceiveAllowance(address _owner, uint256 _subtractedValue) external;\n\n    /// @dev Atomically increases the receive allowance granted to `owner` by the caller.\n    /// This is an alternative to {receive approve} that can be used as a mitigation for problems\n    /// described in {IERC20-approve}.\n    /// Emits an {ReceiveApproval} event indicating the updated receive allowance.\n    /// @param _owner owner of debt token that is being allowed sending it to the caller\n    /// @param _addedValue amount of token to increase allowance\n    function increaseReceiveAllowance(address _owner, uint256 _addedValue) external;\n\n    /// @dev Sets `_amount` as the allowance of `spender` over the caller's tokens.\n    /// Returns a boolean value indicating whether the operation succeeded.\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    /// OR use increase/decrease approval method instead.\n    /// Emits an {ReceiveApproval} event.\n    /// @param _owner owner of debt token that is being allowed sending it to the caller\n    /// @param _amount amount of token allowance\n    function setReceiveApproval(address _owner, uint256 _amount) external;\n\n    /// @dev Returns the remaining number of tokens that `_owner` is allowed to send to `_receiver`\n    /// through {transferFrom}. This is zero by default.\n    /// @param _owner owner of debt token\n    /// @param _receiver wallet that is receiving debt tokens\n    /// @return current token allowance\n    function receiveAllowance(address _owner, address _receiver) external view returns (uint256);\n}\n"
      },
      "contracts/interfaces/IFlashLiquidationReceiver.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\n/// @dev when performing Silo flash liquidation, FlashReceiver contract will receive all collaterals\ninterface IFlashLiquidationReceiver {\n    /// @dev this method is called when doing Silo flash liquidation\n    ///         one can NOT assume, that if _seizedCollateral[i] != 0, then _shareAmountsToRepaid[i] must be 0\n    ///         one should assume, that any combination of amounts is possible\n    ///         on callback, one must call `Silo.repayFor` because at the end of transaction,\n    ///         Silo will check if borrower is solvent.\n    /// @param _user user address, that is liquidated\n    /// @param _assets array of collateral assets received during user liquidation\n    ///         this array contains all assets (collateral borrowed) without any order\n    /// @param _receivedCollaterals array of collateral amounts received during user liquidation\n    ///         indexes of amounts are related to `_assets`,\n    /// @param _shareAmountsToRepaid array of amounts to repay for each asset\n    ///         indexes of amounts are related to `_assets`,\n    /// @param _flashReceiverData data that are passed from sender that executes liquidation\n    function siloLiquidationCallback(\n        address _user,\n        address[] calldata _assets,\n        uint256[] calldata _receivedCollaterals,\n        uint256[] calldata _shareAmountsToRepaid,\n        bytes memory _flashReceiverData\n    ) external;\n}\n"
      },
      "contracts/interfaces/IInterestRateModel.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.13;\n\ninterface IInterestRateModel {\n    /* solhint-disable */\n    struct Config {\n        // uopt ∈ (0, 1) – optimal utilization;\n        int256 uopt;\n        // ucrit ∈ (uopt, 1) – threshold of large utilization;\n        int256 ucrit;\n        // ulow ∈ (0, uopt) – threshold of low utilization\n        int256 ulow;\n        // ki > 0 – integrator gain\n        int256 ki;\n        // kcrit > 0 – proportional gain for large utilization\n        int256 kcrit;\n        // klow ≥ 0 – proportional gain for low utilization\n        int256 klow;\n        // klin ≥ 0 – coefficient of the lower linear bound\n        int256 klin;\n        // beta ≥ 0 - a scaling factor\n        int256 beta;\n        // ri ≥ 0 – initial value of the integrator\n        int256 ri;\n        // Tcrit ≥ 0 - the time during which the utilization exceeds the critical value\n        int256 Tcrit;\n    }\n    /* solhint-enable */\n\n    /// @dev Set dedicated config for given asset in a Silo. Config is per asset per Silo so different assets\n    /// in different Silo can have different configs.\n    /// It will try to call `_silo.accrueInterest(_asset)` before updating config, but it is not guaranteed,\n    /// that this call will be successful, if it fail config will be set anyway.\n    /// @param _silo Silo address for which config should be set\n    /// @param _asset asset address for which config should be set\n    function setConfig(address _silo, address _asset, Config calldata _config) external;\n\n    /// @dev get compound interest rate and update model storage\n    /// @param _asset address of an asset in Silo for which interest rate should be calculated\n    /// @param _blockTimestamp current block timestamp\n    /// @return rcomp compounded interest rate from last update until now (1e18 == 100%)\n    function getCompoundInterestRateAndUpdate(\n        address _asset,\n        uint256 _blockTimestamp\n    ) external returns (uint256 rcomp);\n\n    /// @dev Get config for given asset in a Silo. If dedicated config is not set, default one will be returned.\n    /// @param _silo Silo address for which config should be set\n    /// @param _asset asset address for which config should be set\n    /// @return Config struct for asset in Silo\n    function getConfig(address _silo, address _asset) external view returns (Config memory);\n\n    /// @dev get compound interest rate\n    /// @param _silo address of Silo\n    /// @param _asset address of an asset in Silo for which interest rate should be calculated\n    /// @param _blockTimestamp current block timestamp\n    /// @return rcomp compounded interest rate from last update until now (1e18 == 100%)\n    function getCompoundInterestRate(\n        address _silo,\n        address _asset,\n        uint256 _blockTimestamp\n    ) external view returns (uint256 rcomp);\n\n    /// @dev get current annual interest rate\n    /// @param _silo address of Silo\n    /// @param _asset address of an asset in Silo for which interest rate should be calculated\n    /// @param _blockTimestamp current block timestamp\n    /// @return rcur current annual interest rate (1e18 == 100%)\n    function getCurrentInterestRate(\n        address _silo,\n        address _asset,\n        uint256 _blockTimestamp\n    ) external view returns (uint256 rcur);\n\n    /// @notice get the flag to detect rcomp restriction (zero current interest) due to overflow\n    /// overflow boolean flag to detect rcomp restriction\n    function overflowDetected(\n        address _silo,\n        address _asset,\n        uint256 _blockTimestamp\n    ) external view returns (bool overflow);\n\n    /// @dev pure function that calculates current annual interest rate\n    /// @param _c configuration object, InterestRateModel.Config\n    /// @param _totalBorrowAmount current total borrows for asset\n    /// @param _totalDeposits current total deposits for asset\n    /// @param _interestRateTimestamp timestamp of last interest rate update\n    /// @param _blockTimestamp current block timestamp\n    /// @return rcur current annual interest rate (1e18 == 100%)\n    function calculateCurrentInterestRate(\n        Config memory _c,\n        uint256 _totalDeposits,\n        uint256 _totalBorrowAmount,\n        uint256 _interestRateTimestamp,\n        uint256 _blockTimestamp\n    ) external pure returns (uint256 rcur);\n\n    /// @dev pure function that calculates interest rate based on raw input data\n    /// @param _c configuration object, InterestRateModel.Config\n    /// @param _totalBorrowAmount current total borrows for asset\n    /// @param _totalDeposits current total deposits for asset\n    /// @param _interestRateTimestamp timestamp of last interest rate update\n    /// @param _blockTimestamp current block timestamp\n    /// @return rcomp compounded interest rate from last update until now (1e18 == 100%)\n    /// @return ri current integral part of the rate\n    /// @return Tcrit time during which the utilization exceeds the critical value\n    /// @return overflow boolean flag to detect rcomp restriction\n    function calculateCompoundInterestRateWithOverflowDetection(\n        Config memory _c,\n        uint256 _totalDeposits,\n        uint256 _totalBorrowAmount,\n        uint256 _interestRateTimestamp,\n        uint256 _blockTimestamp\n    ) external pure returns (\n        uint256 rcomp,\n        int256 ri,\n        int256 Tcrit, // solhint-disable-line var-name-mixedcase\n        bool overflow\n    );\n\n    /// @dev pure function that calculates interest rate based on raw input data\n    /// @param _c configuration object, InterestRateModel.Config\n    /// @param _totalBorrowAmount current total borrows for asset\n    /// @param _totalDeposits current total deposits for asset\n    /// @param _interestRateTimestamp timestamp of last interest rate update\n    /// @param _blockTimestamp current block timestamp\n    /// @return rcomp compounded interest rate from last update until now (1e18 == 100%)\n    /// @return ri current integral part of the rate\n    /// @return Tcrit time during which the utilization exceeds the critical value\n    function calculateCompoundInterestRate(\n        Config memory _c,\n        uint256 _totalDeposits,\n        uint256 _totalBorrowAmount,\n        uint256 _interestRateTimestamp,\n        uint256 _blockTimestamp\n    ) external pure returns (\n        uint256 rcomp,\n        int256 ri,\n        int256 Tcrit // solhint-disable-line var-name-mixedcase\n    );\n\n    /// @dev returns decimal points used by model\n    function DP() external pure returns (uint256); // solhint-disable-line func-name-mixedcase\n\n    /// @dev just a helper method to see if address is a InterestRateModel\n    /// @return always true\n    function interestRateModelPing() external pure returns (bytes4);\n}\n"
      },
      "contracts/interfaces/INotificationReceiver.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.13;\n\n/// @title Common interface for Silo Incentive Contract\ninterface INotificationReceiver {\n    /// @dev Informs the contract about token transfer\n    /// @param _token address of the token that was transferred\n    /// @param _from sender\n    /// @param _to receiver\n    /// @param _amount amount that was transferred\n    function onAfterTransfer(address _token, address _from, address _to, uint256 _amount) external;\n\n    /// @dev Sanity check function\n    /// @return always true\n    function notificationReceiverPing() external pure returns (bytes4);\n}\n"
      },
      "contracts/interfaces/IPriceProvider.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.7.6 <0.9.0;\n\n/// @title Common interface for Silo Price Providers\ninterface IPriceProvider {\n    /// @notice Returns \"Time-Weighted Average Price\" for an asset. Calculates TWAP price for quote/asset.\n    /// It unifies all tokens decimal to 18, examples:\n    /// - if asses == quote it returns 1e18\n    /// - if asset is USDC and quote is ETH and ETH costs ~$3300 then it returns ~0.0003e18 WETH per 1 USDC\n    /// @param _asset address of an asset for which to read price\n    /// @return price of asses with 18 decimals, throws when pool is not ready yet to provide price\n    function getPrice(address _asset) external view returns (uint256 price);\n\n    /// @dev Informs if PriceProvider is setup for asset. It does not means PriceProvider can provide price right away.\n    /// Some providers implementations need time to \"build\" buffer for TWAP price,\n    /// so price may not be available yet but this method will return true.\n    /// @param _asset asset in question\n    /// @return TRUE if asset has been setup, otherwise false\n    function assetSupported(address _asset) external view returns (bool);\n\n    /// @notice Gets token address in which prices are quoted\n    /// @return quoteToken address\n    function quoteToken() external view returns (address);\n\n    /// @notice Helper method that allows easily detects, if contract is PriceProvider\n    /// @dev this can save us from simple human errors, in case we use invalid address\n    /// but this should NOT be treated as security check\n    /// @return always true\n    function priceProviderPing() external pure returns (bytes4);\n}\n"
      },
      "contracts/interfaces/IPriceProvidersRepository.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.7.6 <0.9.0;\n\nimport \"./IPriceProvider.sol\";\n\ninterface IPriceProvidersRepository {\n    /// @notice Emitted when price provider is added\n    /// @param newPriceProvider new price provider address\n    event NewPriceProvider(IPriceProvider indexed newPriceProvider);\n\n    /// @notice Emitted when price provider is removed\n    /// @param priceProvider removed price provider address\n    event PriceProviderRemoved(IPriceProvider indexed priceProvider);\n\n    /// @notice Emitted when asset is assigned to price provider\n    /// @param asset assigned asset   address\n    /// @param priceProvider price provider address\n    event PriceProviderForAsset(address indexed asset, IPriceProvider indexed priceProvider);\n\n    /// @notice Register new price provider\n    /// @param _priceProvider address of price provider\n    function addPriceProvider(IPriceProvider _priceProvider) external;\n\n    /// @notice Unregister price provider\n    /// @param _priceProvider address of price provider to be removed\n    function removePriceProvider(IPriceProvider _priceProvider) external;\n\n    /// @notice Sets price provider for asset\n    /// @dev Request for asset price is forwarded to the price provider assigned to that asset\n    /// @param _asset address of an asset for which price provider will be used\n    /// @param _priceProvider address of price provider\n    function setPriceProviderForAsset(address _asset, IPriceProvider _priceProvider) external;\n\n    /// @notice Returns \"Time-Weighted Average Price\" for an asset\n    /// @param _asset address of an asset for which to read price\n    /// @return price TWAP price of a token with 18 decimals\n    function getPrice(address _asset) external view returns (uint256 price);\n\n    /// @notice Gets price provider assigned to an asset\n    /// @param _asset address of an asset for which to get price provider\n    /// @return priceProvider address of price provider\n    function priceProviders(address _asset) external view returns (IPriceProvider priceProvider);\n\n    /// @notice Gets token address in which prices are quoted\n    /// @return quoteToken address\n    function quoteToken() external view returns (address);\n\n    /// @notice Gets manager role address\n    /// @return manager role address\n    function manager() external view returns (address);\n\n    /// @notice Checks if providers are available for an asset\n    /// @param _asset asset address to check\n    /// @return returns TRUE if price feed is ready, otherwise false\n    function providersReadyForAsset(address _asset) external view returns (bool);\n\n    /// @notice Returns true if address is a registered price provider\n    /// @param _provider address of price provider to be removed\n    /// @return true if address is a registered price provider, otherwise false\n    function isPriceProvider(IPriceProvider _provider) external view returns (bool);\n\n    /// @notice Gets number of price providers registered\n    /// @return number of price providers registered\n    function providersCount() external view returns (uint256);\n\n    /// @notice Gets an array of price providers\n    /// @return array of price providers\n    function providerList() external view returns (address[] memory);\n\n    /// @notice Sanity check function\n    /// @return returns always TRUE\n    function priceProvidersRepositoryPing() external pure returns (bytes4);\n}\n"
      },
      "contracts/interfaces/IShareToken.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\n\nimport \"./INotificationReceiver.sol\";\n\ninterface IShareToken is IERC20Metadata {\n    /// @notice Emitted every time receiver is notified about token transfer\n    /// @param notificationReceiver receiver address\n    /// @param success false if TX reverted on `notificationReceiver` side, otherwise true\n    event NotificationSent(\n        INotificationReceiver indexed notificationReceiver,\n        bool success\n    );\n\n    /// @notice Mint method for Silo to create debt position\n    /// @param _account wallet for which to mint token\n    /// @param _amount amount of token to be minted\n    function mint(address _account, uint256 _amount) external;\n\n    /// @notice Burn method for Silo to close debt position\n    /// @param _account wallet for which to burn token\n    /// @param _amount amount of token to be burned\n    function burn(address _account, uint256 _amount) external;\n}\n"
      },
      "contracts/interfaces/ISilo.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.13;\n\nimport \"./IBaseSilo.sol\";\n\ninterface ISilo is IBaseSilo {\n    /// @notice Deposit `_amount` of `_asset` tokens from `msg.sender` to the Silo\n    /// @param _asset The address of the token to deposit\n    /// @param _amount The amount of the token to deposit\n    /// @param _collateralOnly True if depositing collateral only\n    /// @return collateralAmount deposited amount\n    /// @return collateralShare user collateral shares based on deposited amount\n    function deposit(address _asset, uint256 _amount, bool _collateralOnly)\n        external\n        returns (uint256 collateralAmount, uint256 collateralShare);\n\n    /// @notice Router function to deposit `_amount` of `_asset` tokens to the Silo for the `_depositor`\n    /// @param _asset The address of the token to deposit\n    /// @param _depositor The address of the recipient of collateral tokens\n    /// @param _amount The amount of the token to deposit\n    /// @param _collateralOnly True if depositing collateral only\n    /// @return collateralAmount deposited amount\n    /// @return collateralShare `_depositor` collateral shares based on deposited amount\n    function depositFor(address _asset, address _depositor, uint256 _amount, bool _collateralOnly)\n        external\n        returns (uint256 collateralAmount, uint256 collateralShare);\n\n    /// @notice Withdraw `_amount` of `_asset` tokens from the Silo to `msg.sender`\n    /// @param _asset The address of the token to withdraw\n    /// @param _amount The amount of the token to withdraw\n    /// @param _collateralOnly True if withdrawing collateral only deposit\n    /// @return withdrawnAmount withdrawn amount that was transferred to user\n    /// @return withdrawnShare burned share based on `withdrawnAmount`\n    function withdraw(address _asset, uint256 _amount, bool _collateralOnly)\n        external\n        returns (uint256 withdrawnAmount, uint256 withdrawnShare);\n\n    /// @notice Router function to withdraw `_amount` of `_asset` tokens from the Silo for the `_depositor`\n    /// @param _asset The address of the token to withdraw\n    /// @param _depositor The address that originally deposited the collateral tokens being withdrawn,\n    /// it should be the one initiating the withdrawal through the router\n    /// @param _receiver The address that will receive the withdrawn tokens\n    /// @param _amount The amount of the token to withdraw\n    /// @param _collateralOnly True if withdrawing collateral only deposit\n    /// @return withdrawnAmount withdrawn amount that was transferred to `_receiver`\n    /// @return withdrawnShare burned share based on `withdrawnAmount`\n    function withdrawFor(\n        address _asset,\n        address _depositor,\n        address _receiver,\n        uint256 _amount,\n        bool _collateralOnly\n    ) external returns (uint256 withdrawnAmount, uint256 withdrawnShare);\n\n    /// @notice Borrow `_amount` of `_asset` tokens from the Silo to `msg.sender`\n    /// @param _asset The address of the token to borrow\n    /// @param _amount The amount of the token to borrow\n    /// @return debtAmount borrowed amount\n    /// @return debtShare user debt share based on borrowed amount\n    function borrow(address _asset, uint256 _amount) external returns (uint256 debtAmount, uint256 debtShare);\n\n    /// @notice Router function to borrow `_amount` of `_asset` tokens from the Silo for the `_receiver`\n    /// @param _asset The address of the token to borrow\n    /// @param _borrower The address that will take the loan,\n    /// it should be the one initiating the borrowing through the router\n    /// @param _receiver The address of the asset receiver\n    /// @param _amount The amount of the token to borrow\n    /// @return debtAmount borrowed amount\n    /// @return debtShare `_receiver` debt share based on borrowed amount\n    function borrowFor(address _asset, address _borrower, address _receiver, uint256 _amount)\n        external\n        returns (uint256 debtAmount, uint256 debtShare);\n\n    /// @notice Repay `_amount` of `_asset` tokens from `msg.sender` to the Silo\n    /// @param _asset The address of the token to repay\n    /// @param _amount amount of asset to repay, includes interests\n    /// @return repaidAmount amount repaid\n    /// @return burnedShare burned debt share\n    function repay(address _asset, uint256 _amount) external returns (uint256 repaidAmount, uint256 burnedShare);\n\n    /// @notice Allows to repay in behalf of borrower to execute liquidation\n    /// @param _asset The address of the token to repay\n    /// @param _borrower The address of the user to have debt tokens burned\n    /// @param _amount amount of asset to repay, includes interests\n    /// @return repaidAmount amount repaid\n    /// @return burnedShare burned debt share\n    function repayFor(address _asset, address _borrower, uint256 _amount)\n        external\n        returns (uint256 repaidAmount, uint256 burnedShare);\n\n    /// @dev harvest protocol fees from an array of assets\n    /// @return harvestedAmounts amount harvested during tx execution for each of silo asset\n    function harvestProtocolFees() external returns (uint256[] memory harvestedAmounts);\n\n    /// @notice Function to update interests for `_asset` token since the last saved state\n    /// @param _asset The address of the token to be updated\n    /// @return interest accrued interest\n    function accrueInterest(address _asset) external returns (uint256 interest);\n\n    /// @notice this methods does not requires to have tokens in order to liquidate user\n    /// @dev during liquidation process, msg.sender will be notified once all collateral will be send to him\n    /// msg.sender needs to be `IFlashLiquidationReceiver`\n    /// @param _users array of users to liquidate\n    /// @param _flashReceiverData this data will be forward to msg.sender on notification\n    /// @return assets array of all processed assets (collateral + debt, including removed)\n    /// @return receivedCollaterals receivedCollaterals[userId][assetId] => amount\n    /// amounts of collaterals send to `_flashReceiver`\n    /// @return shareAmountsToRepaid shareAmountsToRepaid[userId][assetId] => amount\n    /// required amounts of debt to be repaid\n    function flashLiquidate(address[] memory _users, bytes memory _flashReceiverData)\n        external\n        returns (\n            address[] memory assets,\n            uint256[][] memory receivedCollaterals,\n            uint256[][] memory shareAmountsToRepaid\n        );\n}\n"
      },
      "contracts/interfaces/ISiloFactory.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.13;\n\ninterface ISiloFactory {\n    /// @notice Emitted when Silo is deployed\n    /// @param silo address of deployed Silo\n    /// @param asset address of asset for which Silo was deployed\n    /// @param version version of silo implementation\n    event NewSiloCreated(address indexed silo, address indexed asset, uint128 version);\n\n    /// @notice Must be called by repository on constructor\n    /// @param _siloRepository the SiloRepository to set\n    function initRepository(address _siloRepository) external;\n\n    /// @notice Deploys Silo\n    /// @param _siloAsset unique asset for which Silo is deployed\n    /// @param _version version of silo implementation\n    /// @param _data (optional) data that may be needed during silo creation\n    /// @return silo deployed Silo address\n    function createSilo(address _siloAsset, uint128 _version, bytes memory _data) external returns (address silo);\n\n    /// @dev just a helper method to see if address is a factory\n    function siloFactoryPing() external pure returns (bytes4);\n}\n"
      },
      "contracts/interfaces/ISiloRepository.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.13;\n\nimport \"./ISiloFactory.sol\";\nimport \"./ITokensFactory.sol\";\nimport \"./IPriceProvidersRepository.sol\";\nimport \"./INotificationReceiver.sol\";\nimport \"./IInterestRateModel.sol\";\n\ninterface ISiloRepository {\n    /// @dev protocol fees in precision points (Solvency._PRECISION_DECIMALS), we do allow for fee == 0\n    struct Fees {\n        /// @dev One time protocol fee for opening a borrow position in precision points (Solvency._PRECISION_DECIMALS)\n        uint64 entryFee;\n        /// @dev Protocol revenue share in interest paid in precision points (Solvency._PRECISION_DECIMALS)\n        uint64 protocolShareFee;\n        /// @dev Protocol share in liquidation profit in precision points (Solvency._PRECISION_DECIMALS).\n        /// It's calculated from total collateral amount to be transferred to liquidator.\n        uint64 protocolLiquidationFee;\n    }\n\n    struct SiloVersion {\n        /// @dev Default version of Silo. If set to 0, it means it is not set. By default it is set to 1\n        uint128 byDefault;\n\n        /// @dev Latest added version of Silo. If set to 0, it means it is not set. By default it is set to 1\n        uint128 latest;\n    }\n\n    /// @dev AssetConfig struct represents configurable parameters for each Silo\n    struct AssetConfig {\n        /// @dev Loan-to-Value ratio represents the maximum borrowing power of a specific collateral.\n        ///      For example, if the collateral asset has an LTV of 75%, the user can borrow up to 0.75 worth\n        ///      of quote token in the principal currency for every quote token worth of collateral.\n        ///      value uses 18 decimals eg. 100% == 1e18\n        ///      max valid value is 1e18 so it needs storage of 60 bits\n        uint64 maxLoanToValue;\n\n        /// @dev Liquidation Threshold represents the threshold at which a borrow position will be considered\n        ///      undercollateralized and subject to liquidation for each collateral. For example,\n        ///      if a collateral has a liquidation threshold of 80%, it means that the loan will be\n        ///      liquidated when the borrowAmount value is worth 80% of the collateral value.\n        ///      value uses 18 decimals eg. 100% == 1e18\n        uint64 liquidationThreshold;\n\n        /// @dev interest rate model address\n        IInterestRateModel interestRateModel;\n    }\n\n    event NewDefaultMaximumLTV(uint64 defaultMaximumLTV);\n\n    event NewDefaultLiquidationThreshold(uint64 defaultLiquidationThreshold);\n\n    /// @notice Emitted on new Silo creation\n    /// @param silo deployed Silo address\n    /// @param asset unique asset for deployed Silo\n    /// @param siloVersion version of deployed Silo\n    event NewSilo(address indexed silo, address indexed asset, uint128 siloVersion);\n\n    /// @notice Emitted when new Silo (or existing one) becomes a bridge pool (pool with only bridge tokens).\n    /// @param pool address of the bridge pool, It can be zero address when bridge asset is removed and pool no longer\n    /// is treated as bridge pool\n    event BridgePool(address indexed pool);\n\n    /// @notice Emitted on new bridge asset\n    /// @param newBridgeAsset address of added bridge asset\n    event BridgeAssetAdded(address indexed newBridgeAsset);\n\n    /// @notice Emitted on removed bridge asset\n    /// @param bridgeAssetRemoved address of removed bridge asset\n    event BridgeAssetRemoved(address indexed bridgeAssetRemoved);\n\n    /// @notice Emitted when default interest rate model is changed\n    /// @param newModel address of new interest rate model\n    event InterestRateModel(IInterestRateModel indexed newModel);\n\n    /// @notice Emitted on price provider repository address update\n    /// @param newProvider address of new oracle repository\n    event PriceProvidersRepositoryUpdate(\n        IPriceProvidersRepository indexed newProvider\n    );\n\n    /// @notice Emitted on token factory address update\n    /// @param newTokensFactory address of new token factory\n    event TokensFactoryUpdate(address indexed newTokensFactory);\n\n    /// @notice Emitted on router address update\n    /// @param newRouter address of new router\n    event RouterUpdate(address indexed newRouter);\n\n    /// @notice Emitted on INotificationReceiver address update\n    /// @param newIncentiveContract address of new INotificationReceiver\n    event NotificationReceiverUpdate(INotificationReceiver indexed newIncentiveContract);\n\n    /// @notice Emitted when new Silo version is registered\n    /// @param factory factory address that deploys registered Silo version\n    /// @param siloLatestVersion Silo version of registered Silo\n    /// @param siloDefaultVersion current default Silo version\n    event RegisterSiloVersion(address indexed factory, uint128 siloLatestVersion, uint128 siloDefaultVersion);\n\n    /// @notice Emitted when Silo version is unregistered\n    /// @param factory factory address that deploys unregistered Silo version\n    /// @param siloVersion version that was unregistered\n    event UnregisterSiloVersion(address indexed factory, uint128 siloVersion);\n\n    /// @notice Emitted when default Silo version is updated\n    /// @param newDefaultVersion new default version\n    event SiloDefaultVersion(uint128 newDefaultVersion);\n\n    /// @notice Emitted when default fee is updated\n    /// @param newEntryFee new entry fee\n    /// @param newProtocolShareFee new protocol share fee\n    /// @param newProtocolLiquidationFee new protocol liquidation fee\n    event FeeUpdate(\n        uint64 newEntryFee,\n        uint64 newProtocolShareFee,\n        uint64 newProtocolLiquidationFee\n    );\n\n    /// @notice Emitted when asset config is updated for a silo\n    /// @param silo silo for which asset config is being set\n    /// @param asset asset for which asset config is being set\n    /// @param assetConfig new asset config\n    event AssetConfigUpdate(address indexed silo, address indexed asset, AssetConfig assetConfig);\n\n    /// @notice Emitted when silo (silo factory) version is set for asset\n    /// @param asset asset for which asset config is being set\n    /// @param version Silo version\n    event VersionForAsset(address indexed asset, uint128 version);\n\n    /// @param _siloAsset silo asset\n    /// @return version of Silo that is assigned for provided asset, if not assigned it returns zero (default)\n    function getVersionForAsset(address _siloAsset) external returns (uint128);\n\n    /// @notice setter for `getVersionForAsset` mapping\n    /// @param _siloAsset silo asset\n    /// @param _version version of Silo that will be assigned for `_siloAsset`, zero (default) is acceptable\n    function setVersionForAsset(address _siloAsset, uint128 _version) external;\n\n    /// @notice use this method only when off-chain verification is OFF\n    /// @dev Silo does NOT support rebase and deflationary tokens\n    /// @param _siloAsset silo asset\n    /// @param _siloData (optional) data that may be needed during silo creation\n    /// @return createdSilo address of created silo\n    function newSilo(address _siloAsset, bytes memory _siloData) external returns (address createdSilo);\n\n    /// @notice use this method to deploy new version of Silo for an asset that already has Silo deployed.\n    /// Only owner (DAO) can replace.\n    /// @dev Silo does NOT support rebase and deflationary tokens\n    /// @param _siloAsset silo asset\n    /// @param _siloVersion version of silo implementation. Use 0 for default version which is fine\n    /// for 99% of cases.\n    /// @param _siloData (optional) data that may be needed during silo creation\n    /// @return createdSilo address of created silo\n    function replaceSilo(\n        address _siloAsset,\n        uint128 _siloVersion,\n        bytes memory _siloData\n    ) external returns (address createdSilo);\n\n    /// @notice Set factory contract for debt and collateral tokens for each Silo asset\n    /// @dev Callable only by owner\n    /// @param _tokensFactory address of TokensFactory contract that deploys debt and collateral tokens\n    function setTokensFactory(address _tokensFactory) external;\n\n    /// @notice Set default fees\n    /// @dev Callable only by owner\n    /// @param _fees:\n    /// - _entryFee one time protocol fee for opening a borrow position in precision points\n    /// (Solvency._PRECISION_DECIMALS)\n    /// - _protocolShareFee protocol revenue share in interest paid in precision points\n    /// (Solvency._PRECISION_DECIMALS)\n    /// - _protocolLiquidationFee protocol share in liquidation profit in precision points\n    /// (Solvency._PRECISION_DECIMALS). It's calculated from total collateral amount to be transferred\n    /// to liquidator.\n    function setFees(Fees calldata _fees) external;\n\n    /// @notice Set configuration for given asset in given Silo\n    /// @dev Callable only by owner\n    /// @param _silo Silo address for which config applies\n    /// @param _asset asset address for which config applies\n    /// @param _assetConfig:\n    ///    - _maxLoanToValue maximum Loan-to-Value, for details see `Repository.AssetConfig.maxLoanToValue`\n    ///    - _liquidationThreshold liquidation threshold, for details see `Repository.AssetConfig.maxLoanToValue`\n    ///    - _interestRateModel interest rate model address, for details see `Repository.AssetConfig.interestRateModel`\n    function setAssetConfig(\n        address _silo,\n        address _asset,\n        AssetConfig calldata _assetConfig\n    ) external;\n\n    /// @notice Set default interest rate model\n    /// @dev Callable only by owner\n    /// @param _defaultInterestRateModel default interest rate model\n    function setDefaultInterestRateModel(IInterestRateModel _defaultInterestRateModel) external;\n\n    /// @notice Set default maximum LTV\n    /// @dev Callable only by owner\n    /// @param _defaultMaxLTV default maximum LTV in precision points (Solvency._PRECISION_DECIMALS)\n    function setDefaultMaximumLTV(uint64 _defaultMaxLTV) external;\n\n    /// @notice Set default liquidation threshold\n    /// @dev Callable only by owner\n    /// @param _defaultLiquidationThreshold default liquidation threshold in precision points\n    /// (Solvency._PRECISION_DECIMALS)\n    function setDefaultLiquidationThreshold(uint64 _defaultLiquidationThreshold) external;\n\n    /// @notice Set price provider repository\n    /// @dev Callable only by owner\n    /// @param _repository price provider repository address\n    function setPriceProvidersRepository(IPriceProvidersRepository _repository) external;\n\n    /// @notice Set router contract\n    /// @dev Callable only by owner\n    /// @param _router router address\n    function setRouter(address _router) external;\n\n    /// @notice Set NotificationReceiver contract\n    /// @dev Callable only by owner\n    /// @param _silo silo address for which to set `_notificationReceiver`\n    /// @param _notificationReceiver NotificationReceiver address\n    function setNotificationReceiver(address _silo, INotificationReceiver _notificationReceiver) external;\n\n    /// @notice Adds new bridge asset\n    /// @dev New bridge asset must be unique. Duplicates in bridge assets are not allowed. It's possible to add\n    /// bridge asset that has been removed in the past. Note that all Silos must be synced manually. Callable\n    /// only by owner.\n    /// @param _newBridgeAsset bridge asset address\n    function addBridgeAsset(address _newBridgeAsset) external;\n\n    /// @notice Removes bridge asset\n    /// @dev Note that all Silos must be synced manually. Callable only by owner.\n    /// @param _bridgeAssetToRemove bridge asset address to be removed\n    function removeBridgeAsset(address _bridgeAssetToRemove) external;\n\n    /// @notice Registers new Silo version\n    /// @dev User can choose which Silo version he wants to deploy. It's possible to have multiple versions of Silo.\n    /// Callable only by owner.\n    /// @param _factory factory contract that deploys new version of Silo\n    /// @param _isDefault true if this version should be used as default\n    function registerSiloVersion(ISiloFactory _factory, bool _isDefault) external;\n\n    /// @notice Unregisters Silo version\n    /// @dev Callable only by owner.\n    /// @param _siloVersion Silo version to be unregistered\n    function unregisterSiloVersion(uint128 _siloVersion) external;\n\n    /// @notice Sets default Silo version\n    /// @dev Callable only by owner.\n    /// @param _defaultVersion Silo version to be set as default\n    function setDefaultSiloVersion(uint128 _defaultVersion) external;\n\n    /// @notice Check if contract address is a Silo deployment\n    /// @param _silo address of expected Silo\n    /// @return true if address is Silo deployment, otherwise false\n    function isSilo(address _silo) external view returns (bool);\n\n    /// @notice Get Silo address of asset\n    /// @param _asset address of asset\n    /// @return address of corresponding Silo deployment\n    function getSilo(address _asset) external view returns (address);\n\n    /// @notice Get Silo Factory for given version\n    /// @param _siloVersion version of Silo implementation\n    /// @return ISiloFactory contract that deploys Silos of given version\n    function siloFactory(uint256 _siloVersion) external view returns (ISiloFactory);\n\n    /// @notice Get debt and collateral Token Factory\n    /// @return ITokensFactory contract that deploys debt and collateral tokens\n    function tokensFactory() external view returns (ITokensFactory);\n\n    /// @notice Get Router contract\n    /// @return address of router contract\n    function router() external view returns (address);\n\n    /// @notice Get current bridge assets\n    /// @dev Keep in mind that not all Silos may be synced with current bridge assets so it's possible that some\n    /// assets in that list are not part of given Silo.\n    /// @return address array of bridge assets\n    function getBridgeAssets() external view returns (address[] memory);\n\n    /// @notice Get removed bridge assets\n    /// @dev Keep in mind that not all Silos may be synced with bridge assets so it's possible that some\n    /// assets in that list are still part of given Silo.\n    /// @return address array of bridge assets\n    function getRemovedBridgeAssets() external view returns (address[] memory);\n\n    /// @notice Get maximum LTV for asset in given Silo\n    /// @dev If dedicated config is not set, method returns default config\n    /// @param _silo address of Silo\n    /// @param _asset address of an asset\n    /// @return maximum LTV in precision points (Solvency._PRECISION_DECIMALS)\n    function getMaximumLTV(address _silo, address _asset) external view returns (uint256);\n\n    /// @notice Get Interest Rate Model address for asset in given Silo\n    /// @dev If dedicated config is not set, method returns default config\n    /// @param _silo address of Silo\n    /// @param _asset address of an asset\n    /// @return address of interest rate model\n    function getInterestRateModel(address _silo, address _asset) external view returns (IInterestRateModel);\n\n    /// @notice Get liquidation threshold for asset in given Silo\n    /// @dev If dedicated config is not set, method returns default config\n    /// @param _silo address of Silo\n    /// @param _asset address of an asset\n    /// @return liquidation threshold in precision points (Solvency._PRECISION_DECIMALS)\n    function getLiquidationThreshold(address _silo, address _asset) external view returns (uint256);\n\n    /// @notice Get incentive contract address. Incentive contracts are responsible for distributing rewards\n    /// to debt and/or collateral token holders of given Silo\n    /// @param _silo address of Silo\n    /// @return incentive contract address\n    function getNotificationReceiver(address _silo) external view returns (INotificationReceiver);\n\n    /// @notice Get owner role address of Repository\n    /// @return owner role address\n    function owner() external view returns (address);\n\n    /// @notice get PriceProvidersRepository contract that manages price providers implementations\n    /// @return IPriceProvidersRepository address\n    function priceProvidersRepository() external view returns (IPriceProvidersRepository);\n\n    /// @dev Get protocol fee for opening a borrow position\n    /// @return fee in precision points (Solvency._PRECISION_DECIMALS == 100%)\n    function entryFee() external view returns (uint256);\n\n    /// @dev Get protocol share fee\n    /// @return protocol share fee in precision points (Solvency._PRECISION_DECIMALS == 100%)\n    function protocolShareFee() external view returns (uint256);\n\n    /// @dev Get protocol liquidation fee\n    /// @return protocol liquidation fee in precision points (Solvency._PRECISION_DECIMALS == 100%)\n    function protocolLiquidationFee() external view returns (uint256);\n\n    /// @dev Checks all conditions for new silo creation and throws when not possible to create\n    /// @param _asset address of asset for which you want to create silo\n    /// @param _assetIsABridge bool TRUE when `_asset` is bridge asset, FALSE when it is not\n    function ensureCanCreateSiloFor(address _asset, bool _assetIsABridge) external view;\n\n    function siloRepositoryPing() external pure returns (bytes4);\n}\n"
      },
      "contracts/interfaces/ITokensFactory.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.13;\n\nimport \"./IShareToken.sol\";\n\ninterface ITokensFactory {\n    /// @notice Emitted when collateral token is deployed\n    /// @param token address of deployed collateral token\n    event NewShareCollateralTokenCreated(address indexed token);\n\n    /// @notice Emitted when collateral token is deployed\n    /// @param token address of deployed debt token\n    event NewShareDebtTokenCreated(address indexed token);\n\n    ///@notice Must be called by repository on constructor\n    /// @param _siloRepository the SiloRepository to set\n    function initRepository(address _siloRepository) external;\n\n    /// @notice Deploys collateral token\n    /// @param _name name of the token\n    /// @param _symbol symbol of the token\n    /// @param _asset underlying asset for which token is deployed\n    /// @return address of deployed collateral share token\n    function createShareCollateralToken(\n        string memory _name,\n        string memory _symbol,\n        address _asset\n    ) external returns (IShareToken);\n\n    /// @notice Deploys debt token\n    /// @param _name name of the token\n    /// @param _symbol symbol of the token\n    /// @param _asset underlying asset for which token is deployed\n    /// @return address of deployed debt share token\n    function createShareDebtToken(\n        string memory _name,\n        string memory _symbol,\n        address _asset\n    )\n        external\n        returns (IShareToken);\n\n    /// @dev just a helper method to see if address is a factory\n    /// @return always true\n    function tokensFactoryPing() external pure returns (bytes4);\n}\n"
      },
      "contracts/utils/ShareDebtToken.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.13;\n\nimport \"../interfaces/IERC20R.sol\";\nimport \"../interfaces/ISilo.sol\";\n\nimport \"./ShareToken.sol\";\n\n/// @title ShareDebtToken\n/// @notice ERC20 compatible token representing debt position in Silo\n/// @dev It implements reversed approvals and checks solvency of recipient on transfer.\n///\n/// It is assumed that there is no attack vector on taking someone else's debt because we don't see\n/// economical reason why one would do such thing. For that reason anyone can transfer owner's token\n/// to any recipient as long as receiving wallet approves the transfer. In other words, anyone can\n/// take someone else's debt without asking.\n/// @custom:security-contact security@silo.finance\ncontract ShareDebtToken is IERC20R, ShareToken {\n    /// @dev maps _owner => _recipient => amount\n    mapping(address => mapping(address => uint256)) private _receiveAllowances;\n\n    error OwnerIsZero();\n    error RecipientIsZero();\n    error ShareTransferNotAllowed();\n    error AmountExceedsAllowance();\n    error RecipientNotSolventAfterTransfer();\n\n    constructor (\n        string memory _name,\n        string memory _symbol,\n        address _silo,\n        address _asset\n    ) ERC20(_name, _symbol) ShareToken(_silo, _asset) {\n        // all setup is done in parent contracts, nothing to do here\n    }\n\n    /// @inheritdoc IERC20R\n    function setReceiveApproval(address owner, uint256 _amount) external virtual override {\n        _setReceiveApproval(owner, _msgSender(), _amount);\n    }\n\n    /// @inheritdoc IERC20R\n    function decreaseReceiveAllowance(address _owner, uint256 _subtractedValue) public virtual override {\n        uint256 currentAllowance = _receiveAllowances[_owner][_msgSender()];\n        _setReceiveApproval(_owner, _msgSender(), currentAllowance - _subtractedValue);\n    }\n\n    /// @inheritdoc IERC20R\n    function increaseReceiveAllowance(address _owner, uint256 _addedValue) public virtual override {\n        uint256 currentAllowance = _receiveAllowances[_owner][_msgSender()];\n        _setReceiveApproval(_owner, _msgSender(), currentAllowance + _addedValue);\n    }\n\n    /// @inheritdoc IERC20R\n    function receiveAllowance(address _owner, address _recipient) public view virtual override returns (uint256) {\n        return _receiveAllowances[_owner][_recipient];\n    }\n\n    /// @dev Set allowance\n    /// @param _owner owner of debt token\n    /// @param _recipient wallet that allows `_owner` to send debt to its wallet\n    /// @param _amount amount of token allowed to be transferred\n    function _setReceiveApproval(\n        address _owner,\n        address _recipient,\n        uint256 _amount\n    ) internal virtual {\n        if (_owner == address(0)) revert OwnerIsZero();\n        if (_recipient == address(0)) revert RecipientIsZero();\n\n        _receiveAllowances[_owner][_recipient] = _amount;\n\n        emit ReceiveApproval(_owner, _recipient, _amount);\n    }\n\n    function _beforeTokenTransfer(address _sender, address _recipient, uint256 _amount) internal override {\n        // If we are minting or burning, Silo is responsible to check all necessary conditions\n        if (!_isTransfer(_sender, _recipient)) {\n            return;\n        }\n\n        // Silo forbids having debt and collateral position of the same asset in given Silo\n        if (!silo.borrowPossible(asset, _recipient)) revert ShareTransferNotAllowed();\n\n        // _recipient must approve debt transfer, _sender does not have to\n        uint256 currentAllowance = receiveAllowance(_sender, _recipient);\n        if (currentAllowance < _amount) revert AmountExceedsAllowance();\n\n        // There can't be an underflow in the subtraction because of the previous check\n        unchecked {\n            // update debt allowance\n            _setReceiveApproval(_sender, _recipient, currentAllowance - _amount);\n        }\n    }\n\n    function _afterTokenTransfer(address _sender, address _recipient, uint256 _amount) internal override {\n        ShareToken._afterTokenTransfer(_sender, _recipient, _amount);\n\n        // if we are minting or burning, Silo is responsible to check all necessary conditions\n        // if we are NOT minting and not burning, it means we are transferring\n        // make sure that _recipient is solvent after transfer\n        if (_isTransfer(_sender, _recipient) && !silo.isSolvent(_recipient)) {\n            revert RecipientNotSolventAfterTransfer();\n        }\n        \n        // report mint or transfer\n        _notifyAboutTransfer(_sender, _recipient, _amount);\n    }\n}\n"
      },
      "contracts/utils/ShareToken.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\nimport \"../interfaces/ISilo.sol\";\nimport \"../interfaces/IBaseSilo.sol\";\nimport \"../interfaces/IShareToken.sol\";\nimport \"../interfaces/INotificationReceiver.sol\";\n\n\n/// @title ShareToken\n/// @notice Implements common interface for Silo tokens representing debt or collateral positions.\n/// @custom:security-contact security@silo.finance\nabstract contract ShareToken is ERC20, IShareToken {\n    /// @dev minimal share amount will give us higher precision for shares calculation,\n    /// that way losses caused by division will be reduced to acceptable level\n    uint256 public constant MINIMUM_SHARE_AMOUNT = 1e5;\n\n    /// @notice Silo address for which tokens was deployed\n    ISilo public immutable silo;\n\n    /// @notice asset for which this tokens was deployed\n    address public immutable asset;\n\n    /// @dev decimals that match the original asset decimals\n    uint8 internal immutable _decimals;\n\n    error OnlySilo();\n    error MinimumShareRequirement();\n\n    modifier onlySilo {\n        if (msg.sender != address(silo)) revert OnlySilo();\n\n        _;\n    }\n\n    /// @dev Token is always deployed for specific Silo and asset\n    /// @param _silo Silo address for which tokens was deployed\n    /// @param _asset asset for which this tokens was deployed\n    constructor(address _silo, address _asset) {\n        silo = ISilo(_silo);\n        asset = _asset;\n        _decimals = IERC20Metadata(_asset).decimals();\n    }\n\n    /// @inheritdoc IShareToken\n    function mint(address _account, uint256 _amount) external onlySilo override {\n        _mint(_account, _amount);\n    }\n\n    /// @inheritdoc IShareToken\n    function burn(address _account, uint256 _amount) external onlySilo override {\n        _burn(_account, _amount);\n    }\n\n    /// @inheritdoc IERC20Metadata\n    function symbol() public view virtual override(IERC20Metadata, ERC20) returns (string memory) {\n        return ERC20.symbol();\n    }\n\n    /// @return decimals that match original asset decimals\n    function decimals() public view virtual override(IERC20Metadata, ERC20) returns (uint8) {\n        return _decimals;\n    }\n\n    function _afterTokenTransfer(address _sender, address _recipient, uint256) internal override virtual {\n        // fixing precision error on mint and burn\n        if (_isTransfer(_sender, _recipient)) {\n            return;\n        }\n\n        uint256 total = totalSupply();\n        // we require minimum amount to be present from first mint\n        // and after burning, we do not allow for small leftover\n        if (total != 0 && total < MINIMUM_SHARE_AMOUNT) revert MinimumShareRequirement();\n    }\n\n    /// @dev Report token transfer to incentive contract if one is set\n    /// @param _from sender\n    /// @param _to recipient\n    /// @param _amount amount that was transferred\n    function _notifyAboutTransfer(address _from, address _to, uint256 _amount) internal {\n        INotificationReceiver notificationReceiver =\n            IBaseSilo(silo).siloRepository().getNotificationReceiver(address(silo));\n\n        if (address(notificationReceiver) != address(0)) {\n            // solhint-disable-next-line avoid-low-level-calls\n            (bool success,) = address(notificationReceiver).call(\n                abi.encodeWithSelector(\n                    INotificationReceiver.onAfterTransfer.selector,\n                    address(this),\n                    _from,\n                    _to,\n                    _amount\n                )\n            );\n\n            emit NotificationSent(notificationReceiver, success);\n        }\n    }\n\n    /// @dev checks if operation is \"real\" transfer\n    /// @param _sender sender address\n    /// @param _recipient recipient address\n    /// @return bool true if operation is real transfer, false if it is mint or burn\n    function _isTransfer(address _sender, address _recipient) internal pure returns (bool) {\n        // in order this check to be true, is is required to have:\n        // require(sender != address(0), \"ERC20: transfer from the zero address\");\n        // require(recipient != address(0), \"ERC20: transfer to the zero address\");\n        // on transfer. ERC20 has them, so we good.\n        return _sender != address(0) && _recipient != address(0);\n    }\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "metadata": {
        "useLiteralContent": true
      },
      "libraries": {}
    }
  }}