creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "@openzeppelin/contracts/access/Ownable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    constructor() {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n}\n"
      },
      "@openzeppelin/contracts/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"
      },
      "@openzeppelin/contracts/utils/Context.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.4) (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    function _contextSuffixLength() internal view virtual returns (uint256) {\n        return 0;\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/introspection/IERC165.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"
      },
      "@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Callback for IUniswapV3PoolActions#swap\n/// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface\ninterface IUniswapV3SwapCallback {\n    /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n    /// @dev In the implementation you must pay the pool tokens owed for the swap.\n    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n    /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n    /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n    /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n    /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n    /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n    function uniswapV3SwapCallback(\n        int256 amount0Delta,\n        int256 amount1Delta,\n        bytes calldata data\n    ) external;\n}\n"
      },
      "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.7.5;\npragma abicoder v2;\n\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';\n\n/// @title Router token swapping functionality\n/// @notice Functions for swapping tokens via Uniswap V3\ninterface ISwapRouter is IUniswapV3SwapCallback {\n    struct ExactInputSingleParams {\n        address tokenIn;\n        address tokenOut;\n        uint24 fee;\n        address recipient;\n        uint256 deadline;\n        uint256 amountIn;\n        uint256 amountOutMinimum;\n        uint160 sqrtPriceLimitX96;\n    }\n\n    /// @notice Swaps `amountIn` of one token for as much as possible of another token\n    /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata\n    /// @return amountOut The amount of the received token\n    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);\n\n    struct ExactInputParams {\n        bytes path;\n        address recipient;\n        uint256 deadline;\n        uint256 amountIn;\n        uint256 amountOutMinimum;\n    }\n\n    /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata\n    /// @return amountOut The amount of the received token\n    function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);\n\n    struct ExactOutputSingleParams {\n        address tokenIn;\n        address tokenOut;\n        uint24 fee;\n        address recipient;\n        uint256 deadline;\n        uint256 amountOut;\n        uint256 amountInMaximum;\n        uint160 sqrtPriceLimitX96;\n    }\n\n    /// @notice Swaps as little as possible of one token for `amountOut` of another token\n    /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata\n    /// @return amountIn The amount of the input token\n    function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);\n\n    struct ExactOutputParams {\n        bytes path;\n        address recipient;\n        uint256 deadline;\n        uint256 amountOut;\n        uint256 amountInMaximum;\n    }\n\n    /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata\n    /// @return amountIn The amount of the input token\n    function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);\n}\n"
      },
      "contracts/interfaces/IStreamerInuVault.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.23;\ninterface IStreamerInuVault {\n    /// @dev Emits when STRM token send token to the contract and \n    /// call function receiveTax\n    event UpdatedTaxAmount(uint256 taxAmount);\n    /// @dev Throws if owner pass zero address\n    error ZeroAddress();\n    /// @dev Throws if owner pass zero value\n    error ZeroValue();\n    /// @dev Throws if sender isn't STRM token\n    error AccessDenied();\n    /// @dev Throws if IERC20 approve function returns false\n    error ApproveFailed();\n    /// @dev Throws if contract doesn't have enough balance of token\\\n    /// to make transfer or swap action\n    error NotEnoughBalance();\n    function setRouter(address _newRouter) external;\n    function setPairFee( uint24 _fee) external;\n    function receiveTax(uint256 _amount) external;\n    function sellSi(\n        uint256 _amount,\n        address _recipient,\n        uint256 _amountOutMin\n    ) external;\n    function withdrawUnexpectedTokens(address _token,address _recipient, uint256 _amount) external;\n}\n"
      },
      "contracts/StreamerInuVault.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.23;\nimport {Ownable} from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {ISwapRouter} from \"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\";\nimport {IStreamerInuVault} from \"./interfaces/IStreamerInuVault.sol\";\nimport {IERC165} from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\n/// @title StreamerInu Vault\ncontract StreamerInuVault is IStreamerInuVault, IERC165, Ownable {\n    /// @dev Stores STRM balance which describe reserved tokens for swap\n    uint256 public lastSiBalance;\n    /// @dev Stores address of STRM token\n    address public si;\n    /// @dev Stores address of StreamerInuRouter contract\n    address public siRouter;\n    /// @dev Stores address of USDC token\n    address public usdc;\n    /// @dev Stores fee of SI/USDC pool\n    uint24 public siUsdcPairFee;\n    /// @dev Stores address of Uniswap Swap Router V3\n    ISwapRouter public swapRouterV3;\n\n    /// @dev addresses _siRouter and fee can be equal to 0\n    constructor(address _si, address _usdc,address _siRouter, uint24 _fee, address _swapRouter) {\n        if (\n            _si == address(0) ||\n            _usdc == address(0) ||\n            _swapRouter == address(0)\n        ) {\n            revert ZeroAddress();\n        }\n        si = _si;\n        siRouter = _siRouter;\n        usdc = _usdc;\n        swapRouterV3 = ISwapRouter(_swapRouter);\n        siUsdcPairFee = _fee;\n    }\n\n    /// @notice Set address of StreamerInuRouter SC\n    /// @dev only owner can call the function\n    /// @param _newRouter address of StreamerInuRouter SC\n    function setRouter(address _newRouter) external onlyOwner(){\n        if (_newRouter == address(0)) {\n            revert ZeroAddress();\n        }\n        siRouter = _newRouter;\n    }\n\n    /// @notice Set fee for Uniswap V3 pair STRM/USDC\n    /// @dev only owner can call the function\n    /// @param _fee fee of created Uniswap V3 pair\n    function setPairFee( uint24 _fee) external onlyOwner(){\n        if (_fee == 0) {\n            revert ZeroValue();\n        }\n        siUsdcPairFee = _fee;\n    }\n\n    /// @notice Update amount of reserved STRM tokens for swap\n    /// @dev only STRM token can call the function\n    /// @param _amount amount of received STRM tokens\n    function receiveTax(uint256 _amount) external {\n        if (_msgSender() != si && _msgSender() != siRouter) {\n            revert AccessDenied();\n        }\n        lastSiBalance += _amount;\n        emit UpdatedTaxAmount(_amount);\n    }\n\n    /// @notice Swap reserved STRM tokens to USDC and transfer them to recipient\n    /// @dev only owner can call the function\n    /// @param _amount amount of STRM tokens to swap\n    /// 0 - all available STRM tokens\n    /// if amount is greater then available amount, revert with error \"NotEnoughBalance\"\n    /// @param _recipient address of USDC recipient\n    /// @param _amountOutMin minimum amount of USDC tokens after swap \n    function sellSi(\n        uint256 _amount,\n        address _recipient,\n        uint256 _amountOutMin\n    ) external onlyOwner{\n        IERC20 siToken = IERC20(si);\n        if (_amount == 0) {\n            _amount = lastSiBalance;\n        } else if (_amount > lastSiBalance) {\n            revert NotEnoughBalance();\n        }\n        if(!siToken.approve(address(swapRouterV3), _amount)){\n            revert ApproveFailed();\n        }\n        ISwapRouter.ExactInputSingleParams memory params = ISwapRouter\n            .ExactInputSingleParams(\n                address(siToken),\n                usdc,\n                siUsdcPairFee,\n                _recipient,\n                block.timestamp + 60,\n                _amount,\n                _amountOutMin,\n                0\n            );\n        swapRouterV3.exactInputSingle(params);\n        lastSiBalance-=_amount;\n    }\n\n    /// @notice Admin function in case then some one transfer ERC20 token to the contract\n    /// @dev only owner can call the function\n    /// if _token equals to STRM token, makes check for reservedAmount and current balance\n    /// if _amount > currentBalance - reservedTokens, then revert with error \"NotEnoughBalance\"\n    /// @param _token address of token to withdraw\n    /// @param _recipient address of tokens recipient\n    /// @param _amount amount to withdraw\n    function withdrawUnexpectedTokens(address _token,address _recipient, uint256 _amount) external onlyOwner(){\n        if(_token == address(0) || _recipient == address(0)){\n            revert ZeroAddress();\n        }\n        if(_amount == 0){\n            revert ZeroValue();\n        }\n        IERC20 token = IERC20(_token);\n        uint256 currentBalance = token.balanceOf(address(this));\n        if(_token == si){\n            if(_amount > (currentBalance - lastSiBalance)){\n                revert NotEnoughBalance();\n            }\n        }\n        token.transfer(_recipient, _amount);\n    }\n    \n    /// @inheritdoc IERC165\n    function supportsInterface(bytes4 interfaceId) public pure override returns (bool) {\n        return interfaceId == type(IERC165).interfaceId || interfaceId == type(IStreamerInuVault).interfaceId;\n    }\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 1000
      },
      "viaIR": true,
      "evmVersion": "paris",
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "libraries": {}
    }
  }}