owned this note
owned this note
Published
Linked with GitHub
ERC-1620 v2 (Sep 27, 2019)
===
```
eip: 1620
title: ERC-1620 Money Streaming
author: Paul Razvan Berg (@PaulRBerg) <paul@sablier.finance>
discussions-to: https://github.com/ethereum/EIPs/issues/1620
status: Final
type: Standards Track
category: ERC
created: 2018-11-24
requires: 20
```
## Simple Summary
We define money streaming as continuous payments over a finite period of time. Block timestamps are used as an on-chain proxy for time.
## Abstract
The following describes a standard whereby time is measured using block timestamps and streams are mappings in a master contract.
1. Developer sets up a money streaming contract.
2. A payer, henceforth referred to as sender, can create a stream by depositing funds in the contract and choosing a streaming duration.
3. A payee, henceforth referred to as recipient, can withdraw money from the stream based on its continuous solvency. That is, `payment * (current block timestamp - starting block timestamp)`.
4. The stream can be terminated by either the sender or the recipient.
5. If the stream ended and has not been terminated, the recipient is entitled to withdraw all the remaining balance.
## Motivation
This standardised interface takes a stab at changing the way we think about trust in financial contracts. Thanks to blockchains, payments need not be sent in lumps (as with monthly salaries), as there is less overhead in pay-as-you-go. Money as a function of time would better align incentives in a host of scenarios.
### Use Cases
This is just a preliminary list of use cases. There are other interesting ideas left to explore, such as time-dependent disincetivisation, but, for brevity, we have not included them here.
- Salaries
- Insurance
- Subscriptions
- Consultancies
- Rent
- Parking
- Lending
[Sablier](https://sablier.finance) is a champion project for this ERC. It is what we call the protocol for real-time finance.
## Specification
### Structs
The structure of a stream should be as follows:
- `Stream`
- `deposit`: the amount of money to be streamed
- `ratePerSecond`: the number of tokens allocated each second to the recipient
- `remainingBalance`: the left in the stream
- `startTime`: the unix timestamp for when the stream starts
- `stopTime`: the unix timestamp for when the stream stops
- `recipient`: the address towards which the money is streamed
- `sender`: the address of the party funding the stream
- `tokenAddress`: the ERC20 token to use as streaming currency
- `isEntity`: indicates whether the stream exists or not
```solidity
struct Stream {
uint256 deposit;
uint256 ratePerSecond;
uint256 remainingBalance;
uint256 startTime;
uint256 stopTime;
address recipient;
address sender;
address tokenAddress;
bool isEntity;
}
```
---
### Methods
#### getStream
Returns the stream object with all its properties.
```solidity
function getStream(uint256 streamId) view returns (address sender, address recipient, uint256 deposit, address token, uint256 startTime, uint256 stopTime, uint256 remainingBalance, uint256 ratePerSecond)
```
#### balanceOf
Returns the real-time balance of the account with address `who`.
```solidity
function balanceOf(uint256 streamId, address who) view returns (uint256 balance)
```
#### createStream
Creates a new stream funded by `msg.sender` and paid towards `recipient`. MUST throw if `recipient` is the zero address, the contract itself or the caller themselves. MUST throw if `startTime` is before the current block timestamp. MUST throw if `stopTime` is before `startTime`. MUST throw if `deposit` is not a multiple of the time delta. MUST throw if the contract is not allowed to transfer enough tokens.
**Triggers Event**: [CreateStream](#createstream)
```solidity
function createStream(address recipient, address deposit, address tokenAddress, uint256 startTime, uint256 stopTime) returns (uint256 streamId)
```
#### withdrawFromStream
Withdraws from the contract to the recipient's account.
MUST throw if the caller is not the sender or the recipient. MUST throw if `amount` exceeds the available balance.
**Triggers Event**: [WithdrawFromStream](#withdrawfromstream)
```solidity
function withdrawFromStream(uint256 streamId, uint256 amount) returns (bool success)
```
#### cancelStream
Cancels the stream and transfers the tokens back on a pro rata basis.
MUST throw if the caller is not the sender or the recipient.
**Triggers Event**: [CancelStream](#cancelstream)
```solidity
function cancelStream(uint256 streamId) returns (bool success)
```
---
### Events
#### CreateStream
MUST be triggered when `createStream` is successfully called.
```solidity
event CreateStream(uint256 indexed streamId, address indexed sender, address indexed recipient, uint256 deposit, address tokenAddress, uint256 startTime, uint256 stopTime);
```
#### WithdrawFromStream
MUST be triggered when `withdrawFromStream` is successfully called.
```solidity
event WithdrawFromStream(uint256 indexed streamId, address indexed recipient, uint256 amount);
```
#### CancelStream
MUST be triggered when `cancelStream` is successfully called.
```solidity
event CancelStream(uint256 indexed streamId, address indexed sender, address indexed recipient, uint256 senderBalance, uint256 recipientBalance);
```
## Rationale
This specification is designed to serve as an entry point to the quirky concept of money as a function of time. Several other designs, including payment channels have been considered, but they were deemed dense in assumptions unnecessary for an initial draft.
### Timestamps
Block timestamps are a reasonably secure proxy for time on the blockchain. Although miners handle them, there are game-theoretical incentives to not provide malicious timestamps. [Read this thread](https://ethereum.stackexchange.com/questions/413/can-a-contract-safely-rely-on-block-timestamp) on StackExchange for more details.
The only dangerous scenario we can think of is when ERC-1620 derived implementations end up making up a significant share of the volume of money transferred on Ethereum. It is possible, although unlikely, that some stream recipients will have an incentive to coax miners in bumping the block timestamps for them to profit. But we posit the payoff (a few seconds or minutes times the payment rate) will not be high enough for this kind of attack to be worth it.
## Implementation
- [Sablier](https://github.com/sablierhq/sablier/)
## Additional References
- [Sablier Launch Thread](https://twitter.com/SablierHQ/status/1205533344886411264)
- [Introducing Sablier: Continuous Salaries on Ethereum](https://medium.com/sablier/introducing-sablier-continuous-payments-on-ethereum-c2bf04446d31)
- [Chronos Protocol Ethresear.ch Plasma Proposal](https://ethresear.ch/t/chronos-a-quirky-application-proposal-for-plasma/2928?u=paulrberg)
- [Flipper: Streaming Salaries @ CryptoLife Hackathon](https://devpost.com/software/flipper-3gvl4b)
- [SICOs or Streamed ICOs](https://ethresear.ch/t/chronos-a-quirky-application-proposal-for-plasma/2928/14?u=paulrberg)
- [RICOs or Reversible ICOs](https://twitter.com/feindura/status/1058057076306518017)
- [Andreas Antonopoulos' Keynote on Bitcoin, Lightning and Money Streaming](https://www.youtube.com/watch?v=gF_ZQ_eijPs)
## Copyright
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).