[ Download CSV Export  ] 
 Internal Transactions as a result of Contract Execution
View All
ParentTxHash Block Age From To Value
Contract Source Code Verified (Exact Match)
Contract Name: Streams
Compiler Version: v0.4.25+commit.59dbf8f1
Optimization Enabled: Yes
Runs (Optimiser):  200



  Contract Source Code   Find Similiar Contracts

pragma solidity ^0.4.25;

// File: openzeppelin-solidity/contracts/token/ERC20/IERC20.sol

/**
 * @title ERC20 interface
 * @dev see https://github.com/ethereum/EIPs/issues/20
 */
interface IERC20 {
  function totalSupply() external view returns (uint256);

  function balanceOf(address who) external view returns (uint256);

  function allowance(address owner, address spender)
    external view returns (uint256);

  function transfer(address to, uint256 value) external returns (bool);

  function approve(address spender, uint256 value)
    external returns (bool);

  function transferFrom(address from, address to, uint256 value)
    external returns (bool);

  event Transfer(
    address indexed from,
    address indexed to,
    uint256 value
  );

  event Approval(
    address indexed owner,
    address indexed spender,
    uint256 value
  );
}

// File: openzeppelin-solidity/contracts/ownership/Ownable.sol

/**
 * @title Ownable
 * @dev The Ownable contract has an owner address, and provides basic authorization control
 * functions, this simplifies the implementation of "user permissions".
 */
contract Ownable {
  address private _owner;

  event OwnershipTransferred(
    address indexed previousOwner,
    address indexed newOwner
  );

  /**
   * @dev The Ownable constructor sets the original `owner` of the contract to the sender
   * account.
   */
  constructor() internal {
    _owner = msg.sender;
    emit OwnershipTransferred(address(0), _owner);
  }

  /**
   * @return the address of the owner.
   */
  function owner() public view returns(address) {
    return _owner;
  }

  /**
   * @dev Throws if called by any account other than the owner.
   */
  modifier onlyOwner() {
    require(isOwner());
    _;
  }

  /**
   * @return true if `msg.sender` is the owner of the contract.
   */
  function isOwner() public view returns(bool) {
    return msg.sender == _owner;
  }

  /**
   * @dev Allows the current owner to relinquish control of the contract.
   * @notice Renouncing to ownership will leave the contract without an owner.
   * It will not be possible to call the functions with the `onlyOwner`
   * modifier anymore.
   */
  function renounceOwnership() public onlyOwner {
    emit OwnershipTransferred(_owner, address(0));
    _owner = address(0);
  }

  /**
   * @dev Allows the current owner to transfer control of the contract to a newOwner.
   * @param newOwner The address to transfer ownership to.
   */
  function transferOwnership(address newOwner) public onlyOwner {
    _transferOwnership(newOwner);
  }

  /**
   * @dev Transfers control of the contract to a newOwner.
   * @param newOwner The address to transfer ownership to.
   */
  function _transferOwnership(address newOwner) internal {
    require(newOwner != address(0));
    emit OwnershipTransferred(_owner, newOwner);
    _owner = newOwner;
  }
}

// File: openzeppelin-solidity/contracts/math/SafeMath.sol

/**
 * @title SafeMath
 * @dev Math operations with safety checks that revert on error
 */
library SafeMath {

  /**
  * @dev Multiplies two numbers, reverts on overflow.
  */
  function mul(uint256 a, uint256 b) internal pure returns (uint256) {
    // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
    // benefit is lost if 'b' is also tested.
    // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
    if (a == 0) {
      return 0;
    }

    uint256 c = a * b;
    require(c / a == b);

    return c;
  }

  /**
  * @dev Integer division of two numbers truncating the quotient, reverts on division by zero.
  */
  function div(uint256 a, uint256 b) internal pure returns (uint256) {
    require(b > 0); // Solidity only automatically asserts when dividing by 0
    uint256 c = a / b;
    // assert(a == b * c + a % b); // There is no case in which this doesn't hold

    return c;
  }

  /**
  * @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend).
  */
  function sub(uint256 a, uint256 b) internal pure returns (uint256) {
    require(b <= a);
    uint256 c = a - b;

    return c;
  }

  /**
  * @dev Adds two numbers, reverts on overflow.
  */
  function add(uint256 a, uint256 b) internal pure returns (uint256) {
    uint256 c = a + b;
    require(c >= a);

    return c;
  }

  /**
  * @dev Divides two numbers and returns the remainder (unsigned integer modulo),
  * reverts when dividing by zero.
  */
  function mod(uint256 a, uint256 b) internal pure returns (uint256) {
    require(b != 0);
    return a % b;
  }
}

// File: contracts/streams/IERC1620.sol

/// @title ERC-1620 Money Streaming Standard
/// @dev See https://github.com/ethereum/eips/issues/1620

interface IERC1620 {

  /// @dev This emits when streams are successfully created and added
  ///  in the mapping object.
  event LogCreate(
    uint256 indexed _streamId,
    address indexed _sender,
    address indexed _recipient,
    address _tokenAddress,
    uint256 _startBlock,
    uint256 _stopBlock,
    uint256 _payment,
    uint256 _interval
  );

  /// @dev This emits when the receiver of a stream withdraws a portion
  ///  or all of their available funds from an ongoing stream, without
  ///  stopping it.
  event LogWithdraw(
    uint256 indexed _streamId,
    address indexed _recipient,
    uint256 _funds
  );

  /// @dev This emits when a stream is successfully redeemed and
  ///  all involved parties get their share of the available funds.
  event LogRedeem(
    uint256 indexed _streamId,
    address indexed _sender,
    address indexed _recipient,
    uint256 _senderBalance,
    uint256 _recipientBalance
  );

  /// @dev This emits when an update is successfully committed by
  ///  one of the involved parties.
  event LogConfirmUpdate(
    uint256 indexed _streamId,
    address indexed _confirmer,
    address _newTokenAddress,
    uint256 _newStopBlock,
    uint256 _newPayment,
    uint256 _newInterval
  );

  /// @dev This emits when one of the involved parties revokes
  ///  a proposed update to the stream.
  event LogRevokeUpdate(
    uint256 indexed _streamId,
    address indexed revoker,
    address _newTokenAddress,
    uint256 _newStopBlock,
    uint256 _newPayment,
    uint256 _newInterval
  );

  /// @dev This emits when an update (that is, modifications to
  ///  payment rate, starting or stopping block) is successfully
  ///  approved by all involved parties.
  event LogExecuteUpdate(
    uint256 indexed _newStreamId,
    address indexed _sender,
    address indexed _recipient,
    address _newTokenAddress,
    uint256 _newStopBlock,
    uint256 _newPayment,
    uint256 _newInterval
  );

  /// @notice Returns available funds for the given stream id and address
  /// @dev Streams assigned to the zero address are considered invalid, and
  ///  this function throws for queries about the zero address.
  /// @param _streamId The stream for whom to query the balance
  /// @param _addr The address for whom to query the balance
  /// @return The total funds available to `addr` to withdraw
  function balanceOf(
    uint256 _streamId,
    address _addr
  )
    external
    view
    returns (
      uint256 balance
    );

  /// @notice Returns the full stream data
  /// @dev Throws if `_streamId` doesn't point to a valid stream.
  /// @param _streamId The stream to return data for
  function getStream(
    uint256 _streamId
  )
  external
  view
  returns (
    address _sender,
    address _recipient,
    address _tokenAddress,
    uint256 _balance,
    uint256 _startBlock,
    uint256 _stopBlock,
    uint256 _payment,
    uint256 _interval
  );

  /// @notice Creates a new stream between `msg.sender` and `_recipient`
  /// @dev Throws unless `msg.value` is exactly
  ///  `_payment * ((_stopBlock - _startBlock) / _interval)`.
  ///  Throws if `_startBlock` is not higher than `block.number`.
  ///  Throws if `_stopBlock` is not higher than `_startBlock`.
  ///  Throws if the total streaming duration `_stopBlock - _startBlock`
  ///  is not a multiple of `_interval`.
  /// @param _recipient The stream sender or the payer
  /// @param _recipient The stream recipient or the payee
  /// @param _tokenAddress The token contract address
  /// @param _startBlock The starting time of the stream
  /// @param _stopBlock The stopping time of the stream
  /// @param _payment How much money moves from sender to recipient
  /// @param _interval How often the `payment` moves from sender to recipient
  function create(
    address _sender,
    address _recipient,
    address _tokenAddress,
    uint256 _startBlock,
    uint256 _stopBlock,
    uint256 _payment,
    uint256 _interval
  )
    external;

  /// @notice Withdraws all or a fraction of the available funds
  /// @dev Throws if `_streamId` doesn't point to a valid stream.
  ///  Throws if `msg.sender` is not the recipient of the given `streamId`
  /// @param _streamId The stream to withdraw from
  /// @param _funds The amount of money to withdraw
  function withdraw(
    uint256 _streamId,
    uint256 _funds
  )
    external;

  /// @notice Redeems the stream by distributing the funds to the sender and the recipient
  /// @dev Throws if `_streamId` doesn't point to a valid stream.
  ///  Throws unless `msg.sender` is either the sender or the recipient
  ///  of the given `streamId`.
  /// @param _streamId The stream to stop
  function redeem(
    uint256 _streamId
  )
    external;

  /// @notice Signals one party's willingness to update the stream
  /// @dev Throws if `_streamId` doesn't point to a valid stream.
  ///  Not executed prior to everyone agreeing to the new terms.
  ///  In terms of validation, it works exactly the same as the `create` function.
  /// @param _streamId The stream to update
  /// @param _tokenAddress The token contract address
  /// @param _stopBlock The new stopping time of the stream
  /// @param _payment How much money moves from sender to recipient
  /// @param _interval How often the `payment` moves from sender to recipient
  function confirmUpdate(
    uint256 _streamId,
    address _tokenAddress,
    uint256 _stopBlock,
    uint256 _payment,
    uint256 _interval
  )
    external;

  /// @notice Revokes an update proposed by one of the involved parties
  /// @dev Throws if `_streamId` doesn't point to a valid stream. The parameters
  ///  are merely for logging purposes.
  function revokeUpdate(
    uint256 _streamId,
    address _tokenAddress,
    uint256 _stopBlock,
    uint256 _payment,
    uint256 _interval
  )
    external;
}

// File: contracts/streams/Streams.sol

/// @title Streams - ERC Money Streaming Implementation
/// @author Paul Berg - <[email protected]>

contract Streams is Ownable, IERC1620 {
  using SafeMath for uint256;

  /*
   * Types
   */
  struct Timeframe {
    uint256 start;
    uint256 stop;
  }

  struct Rate {
    uint256 payment;
    uint256 interval;
  }

  struct Stream {
    address sender;
    address recipient;
    address tokenAddress;
    uint256 balance;
    Timeframe timeframe;
    Rate rate;
  }

  /*
   * Storage
   */
  mapping(uint256 => Stream) private streams;
  uint256 private streamNonce;
  mapping(uint256 => mapping(address => bool)) private updates;

  /*
   * Events
   */
  event LogCreate(
    uint256 indexed _streamId,
    address indexed _sender,
    address indexed _recipient,
    address _tokenAddress,
    uint256 _startBlock,
    uint256 _stopBlock,
    uint256 _payment,
    uint256 _interval
  );

  event LogWithdraw(
    uint256 indexed _streamId,
    address indexed _recipient,
    uint256 _funds
  );

  event LogRedeem(
    uint256 indexed _streamId,
    address indexed _sender,
    address indexed _recipient,
    uint256 _senderBalance,
    uint256 _recipientBalance
  );

  event LogConfirmUpdate(
    uint256 indexed _streamId,
    address indexed confirmer,
    address _newTokenAddress,
    uint256 _newStopBlock,
    uint256 _newPayment,
    uint256 _newInterval
  );

  event LogRevokeUpdate(
    uint256 indexed _streamId,
    address indexed revoker,
    address _newTokenAddress,
    uint256 _newStopBlock,
    uint256 _newPayment,
    uint256 _newInterval
  );

  event LogExecuteUpdate(
    uint256 indexed _newStreamId,
    address indexed _sender,
    address indexed _recipient,
    address _newTokenAddress,
    uint256 _newStopBlock,
    uint256 _newPayment,
    uint256 _newInterval
  );

  /*
   * Modifiers
   */
  modifier onlyRecipient(uint256 _streamId) {
    require(
      streams[_streamId].recipient == msg.sender,
      "only the stream recipient is allowed to perform this action"
    );
    _;
  }

  modifier onlySenderOrRecipient(uint256 _streamId) {
    require(
      msg.sender == streams[_streamId].sender ||
      msg.sender == streams[_streamId].recipient,
      "only the sender or the recipient of the stream can perform this action"
    );
    _;
  }

  modifier streamExists(uint256 _streamId) {
    require(
      streams[_streamId].sender != address(0x0),
      "stream doesn't exist"
    );
    _;
  }

  modifier updateConfirmed(uint256 _streamId, address _addr) {
    require(
      updates[_streamId][_addr] == true,
      "msg.sender has not previously confirmed the update"
    );
    _;
  }

  /*
   * Functions
   */
  constructor() public {
    streamNonce = 1;
  }

  function balanceOf(uint256 _streamId, address _addr)
    public
    view
    streamExists(_streamId)
    returns (uint256 balance)
  {
    Stream memory stream = streams[_streamId];
    uint256 deposit = depositOf(_streamId);
    uint256 delta = deltaOf(_streamId);
    uint256 funds = delta.div(stream.rate.interval).mul(stream.rate.payment);

    if (stream.balance != deposit)
      funds = funds.sub(deposit.sub(stream.balance));
    if (_addr == stream.recipient)
      return funds;
    else
      return stream.balance.sub(funds);
  }

  function getStream(uint256 _streamId)
    public
    view
    streamExists(_streamId)
    returns (
      address sender,
      address recipient,
      address tokenAddress,
      uint256 balance,
      uint256 startBlock,
      uint256 stopBlock,
      uint256 payment,
      uint256 interval
  )
  {
    Stream memory stream = streams[_streamId];
    return (
      stream.sender,
      stream.recipient,
      stream.tokenAddress,
      stream.balance,
      stream.timeframe.start,
      stream.timeframe.stop,
      stream.rate.payment,
      stream.rate.interval
    );
  }

  function getUpdate(uint256 _streamId, address _addr)
    public
    view
    streamExists(_streamId)
    returns (bool active)
  {
    return updates[_streamId][_addr];
  }

  function create(
    address _sender,
    address _recipient,
    address _tokenAddress,
    uint256 _startBlock,
    uint256 _stopBlock,
    uint256 _payment,
    uint256 _interval
  )
    public
  {
    verifyTerms(
      _tokenAddress,
      _startBlock,
      _stopBlock,
      _interval
    );

    // both tokens and ether can be streamed
    uint256 deposit = _stopBlock.sub(_startBlock).div(_interval).mul(_payment);
    IERC20 tokenContract = IERC20(_tokenAddress);
    uint256 allowance = tokenContract.allowance(_sender, address(this));
    require(
      allowance >= deposit,
      "contract not allowed to transfer enough tokens"
    );

    // create and log the stream if the deposit is okay
    streams[streamNonce] = Stream({
      sender : _sender,
      recipient : _recipient,
      tokenAddress : _tokenAddress,
      balance : deposit,
      timeframe : Timeframe(_startBlock, _stopBlock),
      rate : Rate(_payment, _interval)
    });
    emit LogCreate(
      streamNonce,
      _sender,
      _recipient,
      _tokenAddress,
      _startBlock,
      _stopBlock,
      _payment,
      _interval
    );
    streamNonce = streamNonce.add(1);

    // apply Checks-Effects-Interactions
    tokenContract.transferFrom(_sender, address(this), deposit);
  }

  function withdraw(
    uint256 _streamId,
    uint256 _funds
  )
    public
    streamExists(_streamId)
    onlyRecipient(_streamId)
  {
    Stream memory stream = streams[_streamId];
    uint256 availableFunds = balanceOf(_streamId, stream.recipient);
    require(availableFunds >= _funds, "not enough funds");

    streams[_streamId].balance = streams[_streamId].balance.sub(_funds);
    emit LogWithdraw(_streamId, stream.recipient, _funds);
    IERC20(stream.tokenAddress).transfer(stream.recipient, _funds);
  }

  function redeem(uint256 _streamId)
    public
    streamExists(_streamId)
    onlySenderOrRecipient(_streamId)
  {
    Stream memory stream = streams[_streamId];
    uint256 senderBalance = balanceOf(_streamId, stream.sender);
    uint256 recipientBalance = balanceOf(_streamId, stream.recipient);
    emit LogRedeem(
      _streamId,
      stream.sender,
      stream.recipient,
      senderBalance,
      recipientBalance
    );
    delete streams[_streamId];
    updates[_streamId][stream.sender] = false;
    updates[_streamId][stream.recipient] = false;

    // reverts when the token address is not an ERC20 contract
    IERC20 tokenContract = IERC20(stream.tokenAddress);
    // saving gas by checking beforehand
    if (recipientBalance > 0)
      tokenContract.transfer(stream.recipient, recipientBalance);
    if (senderBalance > 0)
      tokenContract.transfer(stream.sender, senderBalance);
  }

  function confirmUpdate(
    uint256 _streamId,
    address _tokenAddress,
    uint256 _stopBlock,
    uint256 _payment,
    uint256 _interval
  )
    public
    streamExists(_streamId)
    onlySenderOrRecipient(_streamId)
  {
    onlyNewTerms(
      _streamId,
      _tokenAddress,
      _stopBlock,
      _payment,
      _interval
    );
    verifyTerms(
      _tokenAddress,
      block.number,
      _stopBlock,
      _interval
    );

    emit LogConfirmUpdate(
      _streamId,
      msg.sender,
      _tokenAddress,
      _stopBlock,
      _payment,
      _interval
    );
    updates[_streamId][msg.sender] = true;

    executeUpdate(
      _streamId,
      _tokenAddress,
      _stopBlock,
      _payment,
      _interval
    );
  }

  function revokeUpdate(
    uint256 _streamId,
    address _tokenAddress,
    uint256 _stopBlock,
    uint256 _payment,
    uint256 _interval
  )
    public
    updateConfirmed(_streamId, msg.sender)
  {
    emit LogRevokeUpdate(
      _streamId,
      msg.sender,
      _tokenAddress,
      _stopBlock,
      _payment,
      _interval
    );
    updates[_streamId][msg.sender] = false;
  }

  /*
   * Private
   */
  function deltaOf(uint256 _streamId)
    private
    view
    returns (uint256 delta)
  {
    Stream memory stream = streams[_streamId];
    uint256 startBlock = stream.timeframe.start;

    // before the streaming period finished
    if (block.number < startBlock)
      return 0;

    // after the streaming period finished
    uint256 latestBlock = block.number;
    if (latestBlock > stream.timeframe.stop)
      latestBlock = stream.timeframe.stop;
    return latestBlock.sub(startBlock);
  }

  function depositOf(uint256 _streamId)
    private
    view
    returns (uint256 funds)
  {
    Stream memory stream = streams[_streamId];
    return stream.timeframe.stop
    .sub(stream.timeframe.start)
    .div(stream.rate.interval)
    .mul(stream.rate.payment);
  }

  function onlyNewTerms(
    uint256 _streamId,
    address _tokenAddress,
    uint256 _stopBlock,
    uint256 _payment,
    uint256 _interval
  )
    private
    view
    returns (bool valid)
  {
    require(
    // Disable solium check because of
    // https://github.com/duaraghav8/Solium/issues/175
    // solium-disable-next-line operator-whitespace
      streams[_streamId].tokenAddress != _tokenAddress ||
      streams[_streamId].timeframe.stop != _stopBlock ||
      streams[_streamId].rate.payment != _payment ||
      streams[_streamId].rate.interval != _interval,
      "stream has these terms already"
    );
    return true;
  }

  function verifyTerms(
    address _tokenAddress,
    uint256 _startBlock,
    uint256 _stopBlock,
    uint256 _interval
  )
    private
    view
    returns (bool valid)
  {
    require(
      _tokenAddress != address(0x0),
      "token contract address needs to be provided"
    );
    require(
      _startBlock >= block.number,
      "the start block needs to be higher than the current block number"
    );
    require(
      _stopBlock > _startBlock,
      "the stop block needs to be higher than the start block"
    );
    uint256 delta = _stopBlock - _startBlock;
    require(
      delta >= _interval,
      "the block difference needs to be higher than the payment interval"
    );
    require(
      delta.mod(_interval) == 0,
      "the block difference needs to be a multiple of the payment interval"
    );
    return true;
  }

    // solium-disable-next-line function-order
  function executeUpdate(
    uint256 _streamId,
    address _tokenAddress,
    uint256 _stopBlock,
    uint256 _payment,
    uint256 _interval
  )
    private
    streamExists(_streamId)
  {
    Stream memory stream = streams[_streamId];
    if (updates[_streamId][stream.sender] == false)
      return;
    if (updates[_streamId][stream.recipient] == false)
      return;

    // adjust stop block
    uint256 remainder = _stopBlock.sub(block.number).mod(_interval);
    uint256 adjustedStopBlock = _stopBlock.sub(remainder);
    emit LogExecuteUpdate(
      _streamId,
      stream.sender,
      stream.recipient,
      _tokenAddress,
      adjustedStopBlock,
      _payment,
      _interval
    );
    updates[_streamId][stream.sender] = false;
    updates[_streamId][stream.recipient] = false;

    redeem(
      _streamId
    );
    create(
      stream.sender,
      stream.recipient,
      _tokenAddress,
      block.number,
      adjustedStopBlock,
      _payment,
      _interval
    );
  }
}

    Contract ABI  
[{"constant":true,"inputs":[{"name":"_streamId","type":"uint256"},{"name":"_addr","type":"address"}],"name":"getUpdate","outputs":[{"name":"active","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_streamId","type":"uint256"},{"name":"_addr","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_streamId","type":"uint256"},{"name":"_funds","type":"uint256"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_sender","type":"address"},{"name":"_recipient","type":"address"},{"name":"_tokenAddress","type":"address"},{"name":"_startBlock","type":"uint256"},{"name":"_stopBlock","type":"uint256"},{"name":"_payment","type":"uint256"},{"name":"_interval","type":"uint256"}],"name":"create","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_streamId","type":"uint256"},{"name":"_tokenAddress","type":"address"},{"name":"_stopBlock","type":"uint256"},{"name":"_payment","type":"uint256"},{"name":"_interval","type":"uint256"}],"name":"confirmUpdate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_streamId","type":"uint256"}],"name":"getStream","outputs":[{"name":"sender","type":"address"},{"name":"recipient","type":"address"},{"name":"tokenAddress","type":"address"},{"name":"balance","type":"uint256"},{"name":"startBlock","type":"uint256"},{"name":"stopBlock","type":"uint256"},{"name":"payment","type":"uint256"},{"name":"interval","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_streamId","type":"uint256"},{"name":"_tokenAddress","type":"address"},{"name":"_stopBlock","type":"uint256"},{"name":"_payment","type":"uint256"},{"name":"_interval","type":"uint256"}],"name":"revokeUpdate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_streamId","type":"uint256"}],"name":"redeem","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_streamId","type":"uint256"},{"indexed":true,"name":"_sender","type":"address"},{"indexed":true,"name":"_recipient","type":"address"},{"indexed":false,"name":"_tokenAddress","type":"address"},{"indexed":false,"name":"_startBlock","type":"uint256"},{"indexed":false,"name":"_stopBlock","type":"uint256"},{"indexed":false,"name":"_payment","type":"uint256"},{"indexed":false,"name":"_interval","type":"uint256"}],"name":"LogCreate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_streamId","type":"uint256"},{"indexed":true,"name":"_recipient","type":"address"},{"indexed":false,"name":"_funds","type":"uint256"}],"name":"LogWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_streamId","type":"uint256"},{"indexed":true,"name":"_sender","type":"address"},{"indexed":true,"name":"_recipient","type":"address"},{"indexed":false,"name":"_senderBalance","type":"uint256"},{"indexed":false,"name":"_recipientBalance","type":"uint256"}],"name":"LogRedeem","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_streamId","type":"uint256"},{"indexed":true,"name":"confirmer","type":"address"},{"indexed":false,"name":"_newTokenAddress","type":"address"},{"indexed":false,"name":"_newStopBlock","type":"uint256"},{"indexed":false,"name":"_newPayment","type":"uint256"},{"indexed":false,"name":"_newInterval","type":"uint256"}],"name":"LogConfirmUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_streamId","type":"uint256"},{"indexed":true,"name":"revoker","type":"address"},{"indexed":false,"name":"_newTokenAddress","type":"address"},{"indexed":false,"name":"_newStopBlock","type":"uint256"},{"indexed":false,"name":"_newPayment","type":"uint256"},{"indexed":false,"name":"_newInterval","type":"uint256"}],"name":"LogRevokeUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_newStreamId","type":"uint256"},{"indexed":true,"name":"_sender","type":"address"},{"indexed":true,"name":"_recipient","type":"address"},{"indexed":false,"name":"_newTokenAddress","type":"address"},{"indexed":false,"name":"_newStopBlock","type":"uint256"},{"indexed":false,"name":"_newPayment","type":"uint256"},{"indexed":false,"name":"_newInterval","type":"uint256"}],"name":"LogExecuteUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"}]

  Contract Creation Code Switch To Opcodes View
608060405234801561001057600080fd5b5060008054600160a060020a0319163317808255604051600160a060020a039190911691907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a36001600255611eaa8061006e6000396000f3006080604052600436106100b95763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166326d056cc81146100be5780633656eec2146100f6578063441a3e701461012c5780634b20ae391461014957806363aef68214610182578063715018a6146101af578063894e9a0d146101c45780638da5cb5b1461022c5780638f32d59b1461025d578063c5daca9214610272578063db006a751461029f578063f2fde38b146102b7575b600080fd5b3480156100ca57600080fd5b506100e2600435600160a060020a03602435166102d8565b604080519115158252519081900360200190f35b34801561010257600080fd5b5061011a600435600160a060020a0360243516610366565b60408051918252519081900360200190f35b34801561013857600080fd5b5061014760043560243561051e565b005b34801561015557600080fd5b50610147600160a060020a036004358116906024358116906044351660643560843560a43560c435610838565b34801561018e57600080fd5b50610147600435600160a060020a0360243516604435606435608435610c24565b3480156101bb57600080fd5b50610147610e0e565b3480156101d057600080fd5b506101dc600435610e78565b60408051600160a060020a03998a168152978916602089015295909716868601526060860193909352608085019190915260a084015260c083015260e08201929092529051908190036101000190f35b34801561023857600080fd5b50610241610fa5565b60408051600160a060020a039092168252519081900360200190f35b34801561026957600080fd5b506100e2610fb4565b34801561027e57600080fd5b50610147600435600160a060020a0360243516604435606435608435610fc5565b3480156102ab57600080fd5b506101476004356110e3565b3480156102c357600080fd5b50610147600160a060020a036004351661152c565b6000828152600160205260408120548390600160a060020a03161515610336576040805160e560020a62461bcd0281526020600482015260146024820152600080516020611e5f833981519152604482015290519081900360640190fd5b6000848152600360209081526040808320600160a060020a038716845290915290205460ff1691505b5092915050565b6000610370611e04565b600084815260016020526040812054819081908790600160a060020a031615156103d2576040805160e560020a62461bcd0281526020600482015260146024820152600080516020611e5f833981519152604482015290519081900360640190fd5b600088815260016020818152604092839020835160c0810185528154600160a060020a039081168252938201548416818401526002820154909316838501526003810154606084015283518085018552600482015481526005820154818401526080840152835180850190945260068101548452600701549083015260a081019190915294506104618861154b565b935061046c8861160d565b60a0860151805160209091015191945061049d9161049190869063ffffffff6116ed16565b9063ffffffff61171016565b606086015190925084146104d5576104d26104c586606001518661173e90919063ffffffff16565b839063ffffffff61173e16565b91505b8460200151600160a060020a031687600160a060020a031614156104fb57819550610513565b6060850151610510908363ffffffff61173e16565b95505b505050505092915050565b610526611e04565b6000838152600160205260408120548490600160a060020a03161515610584576040805160e560020a62461bcd0281526020600482015260146024820152600080516020611e5f833981519152604482015290519081900360640190fd5b600085815260016020819052604090912001548590600160a060020a0316331461061e576040805160e560020a62461bcd02815260206004820152603b60248201527f6f6e6c79207468652073747265616d20726563697069656e7420697320616c6c60448201527f6f77656420746f20706572666f726d207468697320616374696f6e0000000000606482015290519081900360840190fd5b600086815260016020818152604092839020835160c0810185528154600160a060020a03908116825293820154841681840190815260028301549094168186015260038201546060820152845180860186526004830154815260058301548185015260808201528451808601909552600682015485526007909101549184019190915260a0810192909252519094506106b8908790610366565b925084831015610712576040805160e560020a62461bcd02815260206004820152601060248201527f6e6f7420656e6f7567682066756e647300000000000000000000000000000000604482015290519081900360640190fd5b600086815260016020526040902060030154610734908663ffffffff61173e16565b60016000888152602001908152602001600020600301819055508360200151600160a060020a0316867f125e889e0ad284210ec4c8448f648c2a782a6d7f2f9d607aefd518485a78c7f4876040518082815260200191505060405180910390a360408085015160208087015183517fa9059cbb000000000000000000000000000000000000000000000000000000008152600160a060020a039182166004820152602481018a9052935192169263a9059cbb92604480830193928290030181600087803b15801561080457600080fd5b505af1158015610818573d6000803e3d6000fd5b505050506040513d602081101561082e57600080fd5b5050505050505050565b600080600061084988888887611755565b5061086e85610491866108628a8c63ffffffff61173e16565b9063ffffffff6116ed16565b604080517fdd62ed3e000000000000000000000000000000000000000000000000000000008152600160a060020a038d8116600483015230602483015291519295508a94509084169163dd62ed3e916044808201926020929091908290030181600087803b1580156108df57600080fd5b505af11580156108f3573d6000803e3d6000fd5b505050506040513d602081101561090957600080fd5b505190508281101561098b576040805160e560020a62461bcd02815260206004820152602e60248201527f636f6e7472616374206e6f7420616c6c6f77656420746f207472616e7366657260448201527f20656e6f75676820746f6b656e73000000000000000000000000000000000000606482015290519081900360840190fd5b60c0604051908101604052808b600160a060020a031681526020018a600160a060020a0316815260200189600160a060020a0316815260200184815260200160408051908101604052808a815260200189815250815260200160408051908101604052808881526020018781525081525060016000600254815260200190815260200160002060008201518160000160006101000a815481600160a060020a030219169083600160a060020a0316021790555060208201518160010160006101000a815481600160a060020a030219169083600160a060020a0316021790555060408201518160020160006101000a815481600160a060020a030219169083600160a060020a03160217905550606082015181600301556080820151816004016000820151816000015560208201518160010155505060a0820151816006016000820151816000015560208201518160010155505090505088600160a060020a03168a600160a060020a03166002547f423751e4650808e365f2255a83be649efc58833777158ceb788549ba102cced18b8b8b8b8b6040518086600160a060020a0316600160a060020a031681526020018581526020018481526020018381526020018281526020019550505050505060405180910390a4600254610b7790600163ffffffff611a3e16565b600255604080517f23b872dd000000000000000000000000000000000000000000000000000000008152600160a060020a038c81166004830152306024830152604482018690529151918416916323b872dd916064808201926020929091908290030181600087803b158015610bec57600080fd5b505af1158015610c00573d6000803e3d6000fd5b505050506040513d6020811015610c1657600080fd5b505050505050505050505050565b6000858152600160205260409020548590600160a060020a03161515610c82576040805160e560020a62461bcd0281526020600482015260146024820152600080516020611e5f833981519152604482015290519081900360640190fd5b6000868152600160205260409020548690600160a060020a0316331480610cc3575060008181526001602081905260409091200154600160a060020a031633145b1515610d65576040805160e560020a62461bcd02815260206004820152604660248201527f6f6e6c79207468652073656e646572206f722074686520726563697069656e7460448201527f206f66207468652073747265616d2063616e20706572666f726d20746869732060648201527f616374696f6e0000000000000000000000000000000000000000000000000000608482015290519081900360a40190fd5b610d728787878787611a50565b50610d7f86438786611755565b5060408051600160a060020a038816815260208101879052808201869052606081018590529051339189917fb34ecde1edd9dca113c19634291cd72c01df1ef42da78fe38bf8d6d5fc68571c9181900360800190a360008781526003602090815260408083203384529091529020805460ff19166001179055610e058787878787611b1b565b50505050505050565b610e16610fb4565b1515610e2157600080fd5b60008054604051600160a060020a03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a36000805473ffffffffffffffffffffffffffffffffffffffff19169055565b600080600080600080600080610e8c611e04565b60008a8152600160205260409020548a90600160a060020a03161515610eea576040805160e560020a62461bcd0281526020600482015260146024820152600080516020611e5f833981519152604482015290519081900360640190fd5b5050506000978852505060016020818152604097889020885160c081018a528154600160a060020a0390811682529382015484168184019081526002830154909416818b019081526003830154606083019081528b51808d018d5260048501548152600585015481870152608084019081528c51808e01909d5260068501548d526007909401548c860190815260a084018d90529251955191519051935180519501519b519251959c919b909a509298509296509094509250565b600054600160a060020a031690565b600054600160a060020a0316331490565b60008581526003602090815260408083203380855292529091205486919060ff161515600114611065576040805160e560020a62461bcd02815260206004820152603260248201527f6d73672e73656e64657220686173206e6f742070726576696f75736c7920636f60448201527f6e6669726d656420746865207570646174650000000000000000000000000000606482015290519081900360840190fd5b60408051600160a060020a038816815260208101879052808201869052606081018590529051339189917fb42e0870648db2bc9e6f3dba1ae2b29628cba8d139077e11e9eddf784d0bd8fd9181900360800190a350505060009384525050600360209081526040808420338552909152909120805460ff1916905550565b6110eb611e04565b600082815260016020526040812054819081908590600160a060020a0316151561114d576040805160e560020a62461bcd0281526020600482015260146024820152600080516020611e5f833981519152604482015290519081900360640190fd5b6000868152600160205260409020548690600160a060020a031633148061118e575060008181526001602081905260409091200154600160a060020a031633145b1515611230576040805160e560020a62461bcd02815260206004820152604660248201527f6f6e6c79207468652073656e646572206f722074686520726563697069656e7460448201527f206f66207468652073747265616d2063616e20706572666f726d20746869732060648201527f616374696f6e0000000000000000000000000000000000000000000000000000608482015290519081900360a40190fd5b600087815260016020818152604092839020835160c0810185528154600160a060020a039081168252938201548416818401526002820154909316838501526003810154606084015283518085018552600482015481526005820154818401526080840152835180850190945260068101548452600701549083015260a081019190915280519096506112c4908890610366565b94506112d4878760200151610366565b93508560200151600160a060020a03168660000151600160a060020a0316887fff72f0afe99649065fe51103b8e6177f865b08295c2a211ac54c13969a08d6b48888604051808381526020018281526020019250505060405180910390a46000878152600160208181526040808420805473ffffffffffffffffffffffffffffffffffffffff199081168255938101805485169055600281018054909416909355600380840185905560048401859055600584018590556006840185905560079093018490558282528084208a51600160a060020a039081168652818452828620805460ff199081169091558d87529484528b8401511685529091528083208054909216909155870151935084111561148057602080870151604080517fa9059cbb000000000000000000000000000000000000000000000000000000008152600160a060020a0392831660048201526024810188905290519186169263a9059cbb926044808401938290030181600087803b15801561145357600080fd5b505af1158015611467573d6000803e3d6000fd5b505050506040513d602081101561147d57600080fd5b50505b6000851115610e05578551604080517fa9059cbb000000000000000000000000000000000000000000000000000000008152600160a060020a0392831660048201526024810188905290519185169163a9059cbb916044808201926020929091908290030181600087803b1580156114f757600080fd5b505af115801561150b573d6000803e3d6000fd5b505050506040513d602081101561152157600080fd5b505050505050505050565b611534610fb4565b151561153f57600080fd5b61154881611d66565b50565b6000611555611e04565b50600082815260016020818152604092839020835160c0810185528154600160a060020a039081168252938201548416818401526002820154909316838501526003810154606084015283518085018552600482015481526005820154818401526080840190815284518086019095526006820154855260079091015484830190815260a084018590529351935190518051920151929361160693909261049192916108629163ffffffff61173e16565b9392505050565b6000611617611e04565b506000828152600160208181526040808420815160c0810183528154600160a060020a03908116825294820154851681850152600282015490941684830152600381015460608501528151808301835260048201548152600582015481850152608085019081528251808401909352600682015483526007909101549282019290925260a083015251519091438211156116b457600093506116e5565b4390508260800151602001518111156116d257506080820151602001515b6116e2818363ffffffff61173e16565b93505b505050919050565b6000808083116116fc57600080fd5b828481151561170757fe5b04949350505050565b600080831515611723576000915061035f565b5082820282848281151561173357fe5b041461160657600080fd5b6000808383111561174e57600080fd5b5050900390565b600080600160a060020a03861615156117de576040805160e560020a62461bcd02815260206004820152602b60248201527f746f6b656e20636f6e74726163742061646472657373206e6565647320746f2060448201527f62652070726f7669646564000000000000000000000000000000000000000000606482015290519081900360840190fd5b4385101561185c576040805160e560020a62461bcd02815260206004820152602481018290527f74686520737461727420626c6f636b206e6565647320746f206265206869676860448201527f6572207468616e207468652063757272656e7420626c6f636b206e756d626572606482015290519081900360840190fd5b8484116118d9576040805160e560020a62461bcd02815260206004820152603660248201527f7468652073746f7020626c6f636b206e6565647320746f20626520686967686560448201527f72207468616e2074686520737461727420626c6f636b00000000000000000000606482015290519081900360840190fd5b5083830382811015611981576040805160e560020a62461bcd02815260206004820152604160248201527f74686520626c6f636b20646966666572656e6365206e6565647320746f20626560448201527f20686967686572207468616e20746865207061796d656e7420696e746572766160648201527f6c00000000000000000000000000000000000000000000000000000000000000608482015290519081900360a40190fd5b611991818463ffffffff611de316565b15611a32576040805160e560020a62461bcd02815260206004820152604360248201527f74686520626c6f636b20646966666572656e6365206e6565647320746f20626560448201527f2061206d756c7469706c65206f6620746865207061796d656e7420696e74657260648201527f76616c0000000000000000000000000000000000000000000000000000000000608482015290519081900360a40190fd5b50600195945050505050565b60008282018381101561160657600080fd5b600085815260016020526040812060020154600160a060020a038681169116141580611a8d57506000868152600160205260409020600501548414155b80611aa957506000868152600160205260409020600601548314155b80611ac557506000868152600160205260409020600701548214155b1515611a32576040805160e560020a62461bcd02815260206004820152601e60248201527f73747265616d20686173207468657365207465726d7320616c72656164790000604482015290519081900360640190fd5b611b23611e04565b60008681526001602052604081205481908890600160a060020a03161515611b83576040805160e560020a62461bcd0281526020600482015260146024820152600080516020611e5f833981519152604482015290519081900360640190fd5b6000898152600160208181526040808420815160c0810183528154600160a060020a03908116825294820154851681850152600282015485168184015260038083015460608301528351808501855260048401548152600584015481870152608083015283518085018552600684015481526007909301548386015260a08201929092528e865290835281852081519094168552929091529091205490945060ff161515611c3057611521565b600089815260036020908152604080832087830151600160a060020a0316845290915290205460ff161515611c6457611521565b611c8485611c78894363ffffffff61173e16565b9063ffffffff611de316565b9250611c96878463ffffffff61173e16565b602080860151865160408051600160a060020a038e811682529481018690528082018c9052606081018b90529051949650918316939216918c917f22d436a2dc9bb1c1f56ac5144978bb667601f889bd8eb47a97760bdd977a700c919081900360800190a460008981526003602081815260408084208851600160a060020a039081168652818452828620805460ff199081169091558f87529484528984015116855290915290912080549091169055611d4f896110e3565b611521846000015185602001518a43868b8b610838565b600160a060020a0381161515611d7b57600080fd5b60008054604051600160a060020a03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b6000811515611df157600080fd5b8183811515611dfc57fe5b069392505050565b6040805161010081018252600080825260208201819052918101829052606081019190915260808101611e35611e47565b8152602001611e42611e47565b905290565b604080518082019091526000808252602082015290560073747265616d20646f65736e2774206578697374000000000000000000000000a165627a7a72305820efe679e8a191b35669d2f49c605160965df3f09a44f8e4fac08ef0533ccd1da50029

   Swarm Source:
bzzr://efe679e8a191b35669d2f49c605160965df3f09a44f8e4fac08ef0533ccd1da5

 

View All
Block Age transaction Difficulty GasUsed Reward
View All
Block Age UncleNumber Difficulty GasUsed Reward