S Price: $0.450771 (-0.06%)
    /

    Contract Diff Checker

    Contract Name:
    AaveEcosystemReserveController

    Contract Source Code:

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.0;
    
    /*
     * @dev Provides information about the current execution context, including the
     * sender of the transaction and its data. While these are generally available
     * via msg.sender and msg.data, they should not be accessed in such a direct
     * manner, since when dealing with GSN meta-transactions the account sending and
     * paying for execution may not be the actual sender (as far as an application
     * is concerned).
     *
     * This contract is only required for intermediate, library-like contracts.
     */
    abstract contract Context {
      function _msgSender() internal view virtual returns (address payable) {
        return payable(msg.sender);
      }
    
      function _msgData() internal view virtual returns (bytes memory) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
      }
    }

    // SPDX-License-Identifier: AGPL-3.0
    pragma solidity ^0.8.0;
    
    /**
     * @dev Interface of the ERC20 standard as defined in the EIP.
     */
    interface IERC20 {
      /**
       * @dev Returns the amount of tokens in existence.
       */
      function totalSupply() external view returns (uint256);
    
      /**
       * @dev Returns the amount of tokens owned by `account`.
       */
      function balanceOf(address account) external view returns (uint256);
    
      /**
       * @dev Moves `amount` tokens from the caller's account to `recipient`.
       *
       * Returns a boolean value indicating whether the operation succeeded.
       *
       * Emits a {Transfer} event.
       */
      function transfer(address recipient, uint256 amount) external returns (bool);
    
      /**
       * @dev Returns the remaining number of tokens that `spender` will be
       * allowed to spend on behalf of `owner` through {transferFrom}. This is
       * zero by default.
       *
       * This value changes when {approve} or {transferFrom} are called.
       */
      function allowance(address owner, address spender) external view returns (uint256);
    
      /**
       * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
       *
       * Returns a boolean value indicating whether the operation succeeded.
       *
       * IMPORTANT: Beware that changing an allowance with this method brings the risk
       * that someone may use both the old and the new allowance by unfortunate
       * transaction ordering. One possible solution to mitigate this race
       * condition is to first reduce the spender's allowance to 0 and set the
       * desired value afterwards:
       * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
       *
       * Emits an {Approval} event.
       */
      function approve(address spender, uint256 amount) external returns (bool);
    
      /**
       * @dev Moves `amount` tokens from `sender` to `recipient` using the
       * allowance mechanism. `amount` is then deducted from the caller's
       * allowance.
       *
       * Returns a boolean value indicating whether the operation succeeded.
       *
       * Emits a {Transfer} event.
       */
      function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
    
      /**
       * @dev Emitted when `value` tokens are moved from one account (`from`) to
       * another (`to`).
       *
       * Note that `value` may be zero.
       */
      event Transfer(address indexed from, address indexed to, uint256 value);
    
      /**
       * @dev Emitted when the allowance of a `spender` for an `owner` is set by
       * a call to {approve}. `value` is the new allowance.
       */
      event Approval(address indexed owner, address indexed spender, uint256 value);
    }

    // SPDX-License-Identifier: MIT
    
    pragma solidity ^0.8.0;
    
    import './Context.sol';
    
    /**
     * @dev Contract module which provides a basic access control mechanism, where
     * there is an account (an owner) that can be granted exclusive access to
     * specific functions.
     *
     * By default, the owner account will be the one that deploys the contract. This
     * can later be changed with {transferOwnership}.
     *
     * This module is used through inheritance. It will make available the modifier
     * `onlyOwner`, which can be applied to your functions to restrict their use to
     * the owner.
     */
    contract Ownable is Context {
      address private _owner;
    
      event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
    
      /**
       * @dev Initializes the contract setting the deployer as the initial owner.
       */
      constructor() {
        address msgSender = _msgSender();
        _owner = msgSender;
        emit OwnershipTransferred(address(0), msgSender);
      }
    
      /**
       * @dev Returns the address of the current owner.
       */
      function owner() public view returns (address) {
        return _owner;
      }
    
      /**
       * @dev Throws if called by any account other than the owner.
       */
      modifier onlyOwner() {
        require(_owner == _msgSender(), 'Ownable: caller is not the owner');
        _;
      }
    
      /**
       * @dev Leaves the contract without owner. It will not be possible to call
       * `onlyOwner` functions anymore. Can only be called by the current owner.
       *
       * NOTE: Renouncing ownership will leave the contract without an owner,
       * thereby removing any functionality that is only available to the owner.
       */
      function renounceOwnership() public virtual onlyOwner {
        emit OwnershipTransferred(_owner, address(0));
        _owner = address(0);
      }
    
      /**
       * @dev Transfers ownership of the contract to a new account (`newOwner`).
       * Can only be called by the current owner.
       */
      function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), 'Ownable: new owner is the zero address');
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
      }
    }

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.10;
    
    import {Ownable} from '@aave/core-v3/contracts/dependencies/openzeppelin/contracts/Ownable.sol';
    import {IStreamable} from './interfaces/IStreamable.sol';
    import {IAdminControlledEcosystemReserve} from './interfaces/IAdminControlledEcosystemReserve.sol';
    import {IAaveEcosystemReserveController} from './interfaces/IAaveEcosystemReserveController.sol';
    import {IERC20} from '@aave/core-v3/contracts/dependencies/openzeppelin/contracts/IERC20.sol';
    
    contract AaveEcosystemReserveController is Ownable, IAaveEcosystemReserveController {
      /**
       * @notice Constructor.
       * @param aaveGovShortTimelock The address of the Aave's governance executor, owning this contract
       */
      constructor(address aaveGovShortTimelock) {
        transferOwnership(aaveGovShortTimelock);
      }
    
      /// @inheritdoc IAaveEcosystemReserveController
      function approve(
        address collector,
        IERC20 token,
        address recipient,
        uint256 amount
      ) external onlyOwner {
        IAdminControlledEcosystemReserve(collector).approve(token, recipient, amount);
      }
    
      /// @inheritdoc IAaveEcosystemReserveController
      function transfer(
        address collector,
        IERC20 token,
        address recipient,
        uint256 amount
      ) external onlyOwner {
        IAdminControlledEcosystemReserve(collector).transfer(token, recipient, amount);
      }
    
      /// @inheritdoc IAaveEcosystemReserveController
      function createStream(
        address collector,
        address recipient,
        uint256 deposit,
        IERC20 tokenAddress,
        uint256 startTime,
        uint256 stopTime
      ) external onlyOwner returns (uint256) {
        return
          IStreamable(collector).createStream(
            recipient,
            deposit,
            address(tokenAddress),
            startTime,
            stopTime
          );
      }
    
      /// @inheritdoc IAaveEcosystemReserveController
      function withdrawFromStream(
        address collector,
        uint256 streamId,
        uint256 funds
      ) external onlyOwner returns (bool) {
        return IStreamable(collector).withdrawFromStream(streamId, funds);
      }
    
      /// @inheritdoc IAaveEcosystemReserveController
      function cancelStream(address collector, uint256 streamId) external onlyOwner returns (bool) {
        return IStreamable(collector).cancelStream(streamId);
      }
    }

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.10;
    
    import {IERC20} from '@aave/core-v3/contracts/dependencies/openzeppelin/contracts/IERC20.sol';
    
    interface IAaveEcosystemReserveController {
      /**
       * @notice Proxy function for ERC20's approve(), pointing to a specific collector contract
       * @param collector The collector contract with funds (Aave ecosystem reserve)
       * @param token The asset address
       * @param recipient Allowance's recipient
       * @param amount Allowance to approve
       **/
      function approve(address collector, IERC20 token, address recipient, uint256 amount) external;
    
      /**
       * @notice Proxy function for ERC20's transfer(), pointing to a specific collector contract
       * @param collector The collector contract with funds (Aave ecosystem reserve)
       * @param token The asset address
       * @param recipient Transfer's recipient
       * @param amount Amount to transfer
       **/
      function transfer(address collector, IERC20 token, address recipient, uint256 amount) external;
    
      /**
       * @notice Proxy function to create a stream of token on a specific collector contract
       * @param collector The collector contract with funds (Aave ecosystem reserve)
       * @param recipient The recipient of the stream of token
       * @param deposit Total amount to be streamed
       * @param tokenAddress The ERC20 token to use as streaming asset
       * @param startTime The unix timestamp for when the stream starts
       * @param stopTime The unix timestamp for when the stream stops
       * @return uint256 The stream id created
       **/
      function createStream(
        address collector,
        address recipient,
        uint256 deposit,
        IERC20 tokenAddress,
        uint256 startTime,
        uint256 stopTime
      ) external returns (uint256);
    
      /**
       * @notice Proxy function to withdraw from a stream of token on a specific collector contract
       * @param collector The collector contract with funds (Aave ecosystem reserve)
       * @param streamId The id of the stream to withdraw tokens from
       * @param funds Amount to withdraw
       * @return bool If the withdrawal finished properly
       **/
      function withdrawFromStream(
        address collector,
        uint256 streamId,
        uint256 funds
      ) external returns (bool);
    
      /**
       * @notice Proxy function to cancel a stream of token on a specific collector contract
       * @param collector The collector contract with funds (Aave ecosystem reserve)
       * @param streamId The id of the stream to cancel
       * @return bool If the cancellation happened correctly
       **/
      function cancelStream(address collector, uint256 streamId) external returns (bool);
    }

    // SPDX-License-Identifier: GPL-3.0
    pragma solidity ^0.8.10;
    
    import {IERC20} from '@aave/core-v3/contracts/dependencies/openzeppelin/contracts/IERC20.sol';
    
    interface IAdminControlledEcosystemReserve {
      /** @notice Emitted when the funds admin changes
       * @param fundsAdmin The new funds admin
       **/
      event NewFundsAdmin(address indexed fundsAdmin);
    
      /** @notice Returns the mock ETH reference address
       * @return address The address
       **/
      function ETH_MOCK_ADDRESS() external pure returns (address);
    
      /**
       * @notice Return the funds admin, only entity to be able to interact with this contract (controller of reserve)
       * @return address The address of the funds admin
       **/
      function getFundsAdmin() external view returns (address);
    
      /**
       * @dev Function for the funds admin to give ERC20 allowance to other parties
       * @param token The address of the token to give allowance from
       * @param recipient Allowance's recipient
       * @param amount Allowance to approve
       **/
      function approve(IERC20 token, address recipient, uint256 amount) external;
    
      /**
       * @notice Function for the funds admin to transfer ERC20 tokens to other parties
       * @param token The address of the token to transfer
       * @param recipient Transfer's recipient
       * @param amount Amount to transfer
       **/
      function transfer(IERC20 token, address recipient, uint256 amount) external;
    }

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.10;
    
    interface IStreamable {
      struct Stream {
        uint256 deposit;
        uint256 ratePerSecond;
        uint256 remainingBalance;
        uint256 startTime;
        uint256 stopTime;
        address recipient;
        address sender;
        address tokenAddress;
        bool isEntity;
      }
    
      event CreateStream(
        uint256 indexed streamId,
        address indexed sender,
        address indexed recipient,
        uint256 deposit,
        address tokenAddress,
        uint256 startTime,
        uint256 stopTime
      );
    
      event WithdrawFromStream(uint256 indexed streamId, address indexed recipient, uint256 amount);
    
      event CancelStream(
        uint256 indexed streamId,
        address indexed sender,
        address indexed recipient,
        uint256 senderBalance,
        uint256 recipientBalance
      );
    
      function balanceOf(uint256 streamId, address who) external view returns (uint256 balance);
    
      function getStream(
        uint256 streamId
      )
        external
        view
        returns (
          address sender,
          address recipient,
          uint256 deposit,
          address token,
          uint256 startTime,
          uint256 stopTime,
          uint256 remainingBalance,
          uint256 ratePerSecond
        );
    
      function createStream(
        address recipient,
        uint256 deposit,
        address tokenAddress,
        uint256 startTime,
        uint256 stopTime
      ) external returns (uint256 streamId);
    
      function withdrawFromStream(uint256 streamId, uint256 funds) external returns (bool);
    
      function cancelStream(uint256 streamId) external returns (bool);
    
      function initialize(address fundsAdmin) external;
    }

    Contract Name:
    AaveEcosystemReserveController

    Contract Source Code:

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.0;
    
    /*
     * @dev Provides information about the current execution context, including the
     * sender of the transaction and its data. While these are generally available
     * via msg.sender and msg.data, they should not be accessed in such a direct
     * manner, since when dealing with GSN meta-transactions the account sending and
     * paying for execution may not be the actual sender (as far as an application
     * is concerned).
     *
     * This contract is only required for intermediate, library-like contracts.
     */
    abstract contract Context {
      function _msgSender() internal view virtual returns (address payable) {
        return payable(msg.sender);
      }
    
      function _msgData() internal view virtual returns (bytes memory) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
      }
    }

    // SPDX-License-Identifier: AGPL-3.0
    pragma solidity ^0.8.0;
    
    /**
     * @dev Interface of the ERC20 standard as defined in the EIP.
     */
    interface IERC20 {
      /**
       * @dev Returns the amount of tokens in existence.
       */
      function totalSupply() external view returns (uint256);
    
      /**
       * @dev Returns the amount of tokens owned by `account`.
       */
      function balanceOf(address account) external view returns (uint256);
    
      /**
       * @dev Moves `amount` tokens from the caller's account to `recipient`.
       *
       * Returns a boolean value indicating whether the operation succeeded.
       *
       * Emits a {Transfer} event.
       */
      function transfer(address recipient, uint256 amount) external returns (bool);
    
      /**
       * @dev Returns the remaining number of tokens that `spender` will be
       * allowed to spend on behalf of `owner` through {transferFrom}. This is
       * zero by default.
       *
       * This value changes when {approve} or {transferFrom} are called.
       */
      function allowance(address owner, address spender) external view returns (uint256);
    
      /**
       * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
       *
       * Returns a boolean value indicating whether the operation succeeded.
       *
       * IMPORTANT: Beware that changing an allowance with this method brings the risk
       * that someone may use both the old and the new allowance by unfortunate
       * transaction ordering. One possible solution to mitigate this race
       * condition is to first reduce the spender's allowance to 0 and set the
       * desired value afterwards:
       * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
       *
       * Emits an {Approval} event.
       */
      function approve(address spender, uint256 amount) external returns (bool);
    
      /**
       * @dev Moves `amount` tokens from `sender` to `recipient` using the
       * allowance mechanism. `amount` is then deducted from the caller's
       * allowance.
       *
       * Returns a boolean value indicating whether the operation succeeded.
       *
       * Emits a {Transfer} event.
       */
      function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
    
      /**
       * @dev Emitted when `value` tokens are moved from one account (`from`) to
       * another (`to`).
       *
       * Note that `value` may be zero.
       */
      event Transfer(address indexed from, address indexed to, uint256 value);
    
      /**
       * @dev Emitted when the allowance of a `spender` for an `owner` is set by
       * a call to {approve}. `value` is the new allowance.
       */
      event Approval(address indexed owner, address indexed spender, uint256 value);
    }

    // SPDX-License-Identifier: MIT
    
    pragma solidity ^0.8.0;
    
    import './Context.sol';
    
    /**
     * @dev Contract module which provides a basic access control mechanism, where
     * there is an account (an owner) that can be granted exclusive access to
     * specific functions.
     *
     * By default, the owner account will be the one that deploys the contract. This
     * can later be changed with {transferOwnership}.
     *
     * This module is used through inheritance. It will make available the modifier
     * `onlyOwner`, which can be applied to your functions to restrict their use to
     * the owner.
     */
    contract Ownable is Context {
      address private _owner;
    
      event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
    
      /**
       * @dev Initializes the contract setting the deployer as the initial owner.
       */
      constructor() {
        address msgSender = _msgSender();
        _owner = msgSender;
        emit OwnershipTransferred(address(0), msgSender);
      }
    
      /**
       * @dev Returns the address of the current owner.
       */
      function owner() public view returns (address) {
        return _owner;
      }
    
      /**
       * @dev Throws if called by any account other than the owner.
       */
      modifier onlyOwner() {
        require(_owner == _msgSender(), 'Ownable: caller is not the owner');
        _;
      }
    
      /**
       * @dev Leaves the contract without owner. It will not be possible to call
       * `onlyOwner` functions anymore. Can only be called by the current owner.
       *
       * NOTE: Renouncing ownership will leave the contract without an owner,
       * thereby removing any functionality that is only available to the owner.
       */
      function renounceOwnership() public virtual onlyOwner {
        emit OwnershipTransferred(_owner, address(0));
        _owner = address(0);
      }
    
      /**
       * @dev Transfers ownership of the contract to a new account (`newOwner`).
       * Can only be called by the current owner.
       */
      function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), 'Ownable: new owner is the zero address');
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
      }
    }

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.10;
    
    import {Ownable} from '@aave/core-v3/contracts/dependencies/openzeppelin/contracts/Ownable.sol';
    import {IStreamable} from './interfaces/IStreamable.sol';
    import {IAdminControlledEcosystemReserve} from './interfaces/IAdminControlledEcosystemReserve.sol';
    import {IAaveEcosystemReserveController} from './interfaces/IAaveEcosystemReserveController.sol';
    import {IERC20} from '@aave/core-v3/contracts/dependencies/openzeppelin/contracts/IERC20.sol';
    
    contract AaveEcosystemReserveController is Ownable, IAaveEcosystemReserveController {
      /**
       * @notice Constructor.
       * @param aaveGovShortTimelock The address of the Aave's governance executor, owning this contract
       */
      constructor(address aaveGovShortTimelock) {
        transferOwnership(aaveGovShortTimelock);
      }
    
      /// @inheritdoc IAaveEcosystemReserveController
      function approve(
        address collector,
        IERC20 token,
        address recipient,
        uint256 amount
      ) external onlyOwner {
        IAdminControlledEcosystemReserve(collector).approve(token, recipient, amount);
      }
    
      /// @inheritdoc IAaveEcosystemReserveController
      function transfer(
        address collector,
        IERC20 token,
        address recipient,
        uint256 amount
      ) external onlyOwner {
        IAdminControlledEcosystemReserve(collector).transfer(token, recipient, amount);
      }
    
      /// @inheritdoc IAaveEcosystemReserveController
      function createStream(
        address collector,
        address recipient,
        uint256 deposit,
        IERC20 tokenAddress,
        uint256 startTime,
        uint256 stopTime
      ) external onlyOwner returns (uint256) {
        return
          IStreamable(collector).createStream(
            recipient,
            deposit,
            address(tokenAddress),
            startTime,
            stopTime
          );
      }
    
      /// @inheritdoc IAaveEcosystemReserveController
      function withdrawFromStream(
        address collector,
        uint256 streamId,
        uint256 funds
      ) external onlyOwner returns (bool) {
        return IStreamable(collector).withdrawFromStream(streamId, funds);
      }
    
      /// @inheritdoc IAaveEcosystemReserveController
      function cancelStream(address collector, uint256 streamId) external onlyOwner returns (bool) {
        return IStreamable(collector).cancelStream(streamId);
      }
    }

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.10;
    
    import {IERC20} from '@aave/core-v3/contracts/dependencies/openzeppelin/contracts/IERC20.sol';
    
    interface IAaveEcosystemReserveController {
      /**
       * @notice Proxy function for ERC20's approve(), pointing to a specific collector contract
       * @param collector The collector contract with funds (Aave ecosystem reserve)
       * @param token The asset address
       * @param recipient Allowance's recipient
       * @param amount Allowance to approve
       **/
      function approve(address collector, IERC20 token, address recipient, uint256 amount) external;
    
      /**
       * @notice Proxy function for ERC20's transfer(), pointing to a specific collector contract
       * @param collector The collector contract with funds (Aave ecosystem reserve)
       * @param token The asset address
       * @param recipient Transfer's recipient
       * @param amount Amount to transfer
       **/
      function transfer(address collector, IERC20 token, address recipient, uint256 amount) external;
    
      /**
       * @notice Proxy function to create a stream of token on a specific collector contract
       * @param collector The collector contract with funds (Aave ecosystem reserve)
       * @param recipient The recipient of the stream of token
       * @param deposit Total amount to be streamed
       * @param tokenAddress The ERC20 token to use as streaming asset
       * @param startTime The unix timestamp for when the stream starts
       * @param stopTime The unix timestamp for when the stream stops
       * @return uint256 The stream id created
       **/
      function createStream(
        address collector,
        address recipient,
        uint256 deposit,
        IERC20 tokenAddress,
        uint256 startTime,
        uint256 stopTime
      ) external returns (uint256);
    
      /**
       * @notice Proxy function to withdraw from a stream of token on a specific collector contract
       * @param collector The collector contract with funds (Aave ecosystem reserve)
       * @param streamId The id of the stream to withdraw tokens from
       * @param funds Amount to withdraw
       * @return bool If the withdrawal finished properly
       **/
      function withdrawFromStream(
        address collector,
        uint256 streamId,
        uint256 funds
      ) external returns (bool);
    
      /**
       * @notice Proxy function to cancel a stream of token on a specific collector contract
       * @param collector The collector contract with funds (Aave ecosystem reserve)
       * @param streamId The id of the stream to cancel
       * @return bool If the cancellation happened correctly
       **/
      function cancelStream(address collector, uint256 streamId) external returns (bool);
    }

    // SPDX-License-Identifier: GPL-3.0
    pragma solidity ^0.8.10;
    
    import {IERC20} from '@aave/core-v3/contracts/dependencies/openzeppelin/contracts/IERC20.sol';
    
    interface IAdminControlledEcosystemReserve {
      /** @notice Emitted when the funds admin changes
       * @param fundsAdmin The new funds admin
       **/
      event NewFundsAdmin(address indexed fundsAdmin);
    
      /** @notice Returns the mock ETH reference address
       * @return address The address
       **/
      function ETH_MOCK_ADDRESS() external pure returns (address);
    
      /**
       * @notice Return the funds admin, only entity to be able to interact with this contract (controller of reserve)
       * @return address The address of the funds admin
       **/
      function getFundsAdmin() external view returns (address);
    
      /**
       * @dev Function for the funds admin to give ERC20 allowance to other parties
       * @param token The address of the token to give allowance from
       * @param recipient Allowance's recipient
       * @param amount Allowance to approve
       **/
      function approve(IERC20 token, address recipient, uint256 amount) external;
    
      /**
       * @notice Function for the funds admin to transfer ERC20 tokens to other parties
       * @param token The address of the token to transfer
       * @param recipient Transfer's recipient
       * @param amount Amount to transfer
       **/
      function transfer(IERC20 token, address recipient, uint256 amount) external;
    }

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.10;
    
    interface IStreamable {
      struct Stream {
        uint256 deposit;
        uint256 ratePerSecond;
        uint256 remainingBalance;
        uint256 startTime;
        uint256 stopTime;
        address recipient;
        address sender;
        address tokenAddress;
        bool isEntity;
      }
    
      event CreateStream(
        uint256 indexed streamId,
        address indexed sender,
        address indexed recipient,
        uint256 deposit,
        address tokenAddress,
        uint256 startTime,
        uint256 stopTime
      );
    
      event WithdrawFromStream(uint256 indexed streamId, address indexed recipient, uint256 amount);
    
      event CancelStream(
        uint256 indexed streamId,
        address indexed sender,
        address indexed recipient,
        uint256 senderBalance,
        uint256 recipientBalance
      );
    
      function balanceOf(uint256 streamId, address who) external view returns (uint256 balance);
    
      function getStream(
        uint256 streamId
      )
        external
        view
        returns (
          address sender,
          address recipient,
          uint256 deposit,
          address token,
          uint256 startTime,
          uint256 stopTime,
          uint256 remainingBalance,
          uint256 ratePerSecond
        );
    
      function createStream(
        address recipient,
        uint256 deposit,
        address tokenAddress,
        uint256 startTime,
        uint256 stopTime
      ) external returns (uint256 streamId);
    
      function withdrawFromStream(uint256 streamId, uint256 funds) external returns (bool);
    
      function cancelStream(uint256 streamId) external returns (bool);
    
      function initialize(address fundsAdmin) external;
    }

    Context size (optional):