Skip to content

Commit

Permalink
feat: add graphs, faq, redirects, and v1 docs
Browse files Browse the repository at this point in the history
  • Loading branch information
maxdesalle committed Mar 30, 2023
1 parent 85912d2 commit f01ea9c
Show file tree
Hide file tree
Showing 14 changed files with 622 additions and 15 deletions.
18 changes: 9 additions & 9 deletions docs/concepts/protocol/02-stream-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ title: "Types of Streams"
## Linear Streams

Linear streams are the simplest type of stream. They follow a straight line that goes up and to the right on a graph,
which corresponds to the identity function $f(x) = x$.
which corresponds to the identity function $f(x) = x$ ([see on Desmos](https://www.desmos.com/calculator/fqajxzhbx8)).

With linear streams, the payment rate remains constant, meaning that the same fraction of the deposit amount is streamed
to the recipient every second. This provides greater predictability and is very easy to understand because of how
Expand All @@ -17,7 +17,7 @@ intuitive it is. Imagine a diagonal line going up and to the right – that's ho

It is possible to add a **cliff** to a linear stream, which sets a cut-off point for releasing assets. Prior to the
cliff ,the recipient cannot withdraw any assets, although the stream continues to accrue them. After the cliff, the
stream operates like a typical linear stream.
stream operates like a typical linear stream ([see on Desmos](https://www.desmos.com/calculator/mk7422ivwp)).

Cliffs a great fit if you are looking to vest ERC-20 assets, as it allows you to, for example, have a 1-year cliff, and
then 3 additional years of linear streaming. If the stream is meant for an employee, you can make it cancellable so that
Expand Down Expand Up @@ -45,17 +45,17 @@ the $f(x) = log(x)$ function.
### Exponential Streams

Part of the Sablier Dynamic offering, **exponential streams allow for streams where the recipients receive more and more
tokens as time moves forward**.
tokens as time moves forward** ([see on Desmos](https://www.desmos.com/calculator/xgzguiata7)).

For our math junkies out there, it's somewhat similar to the $f(x) = e^x - 1$ function. This is especially a great fit
if you are looking to airdrop tokens to your community, as instead of receiving the tokens all at once (no streaming) or
in a linear fashion (linear stream), your community members will receive the majority of the tokens towards the end of
the stream. **This incentivizes long-term behavior and a constructive attitude**.
This is especially a great fit if you are looking to airdrop tokens to your community, as instead of receiving the
tokens all at once (no streaming) or in a linear fashion (linear stream), your community members will receive the
majority of the tokens towards the end of the stream. **This incentivizes long-term behavior and a constructive
attitude**.

### Exponential Cliff Streams

Part of the Sablier Dynamic offering, the Exponential Cliff streaming curve is a mix between the Cliff Stream and the
Exponential streaming curves.
Exponential streaming curves ([see on Desmos](https://www.desmos.com/calculator/rzoygqlixt)).

**The stream starts with a cliff** (however long you want), a specific amount is then instantly unlocked and streamed
over to the recipient, and from the rest of the streaming curve is an exponential.
Expand All @@ -67,7 +67,7 @@ stream ends.
### Traditional Unlock Streams

Part of the Sablier Dynamic offering, the Traditional Unlock streaming curve is literally just that: a traditional
vesting contract with periodic unlocks.
vesting contract with periodic unlocks ([see on Desmos](https://www.desmos.com/calculator/wf6uogrwei)).

Every month, quarter or year (or an other time setting) depending on how you configure it, a specific amount will be
unlocked and sent over to the recipient.
Expand Down
5 changes: 5 additions & 0 deletions docs/contracts/v1/contracts/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"collapsed": true,
"label": "Contracts",
"position": 1
}
141 changes: 141 additions & 0 deletions docs/contracts/v1/contracts/constant-functions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
---
id: constant-functions
title: Constant Functions
sidebar_position: 3
---

## Get Stream

Returns all properties for the provided stream id.

```solidity
function getStream(uint256 streamId) view returns (address sender, address recipient, address tokenAddress, uint256 balance, uint256 startTime, uint256 stopTime, uint256 remainingBalance, uint256 ratePerSecond)
```

- `streamId`: The id of the stream to query.
- `RETURN`
- `sender`: The address that created and funded the stream.
- `recipient`: The address towards which the tokens are streamed.
- `tokenAddress`: The address of the ERC-20 token used as streaming currency.
- `startTime`: The unix timestamp for when the stream starts, in seconds.
- `stopTime`: The unix timestamp for when the stream stops, in seconds.
- `remainingBalance`: How much tokens are still allocated to this stream, in the smart contract.
- `ratePerSecond`: How much tokens are allocated from the sender to the recipient every second.

### Solidity

```solidity
Sablier sablier = Sablier(0xabcd...);
uint256 streamId = 42;
(uint256 sender, uint256 recipient, uint256 deposit, address tokenAddress, uint256 startTime, uint256 stopTime, uint256 remainingBalance, uint256 ratePerSecond) = sablier.getStream(streamId);
```

### Ethers.js

```javascript
const sablier = new ethers.Contract(0xabcd..., sablierABI, signerOrProvider);
const streamId = 42;
const stream = await sablier.getStream(streamId);‌
```

---

## Balance Of

Returns the real-time balance of an account with regards to a specific stream.

```solidity
function balanceOf(uint256 streamId, address who) view returns (uint256)
```

- `streamId`: The id of the stream for which to query the balance.
- `who`: The address for which to query the balance.
- `RETURN`: The available balance in units of the underlying ERC-20 token.

:::info

This is the amount of tokens that can be withdrawn from the contract, not the total amount of tokens streamed. If the
contract streamed 1,000 tokens to Bob, but Bob withdrew 400 tokens already, this function will return 600 and not 1,000.

:::

### Solidity

```solidity
Sablier sablier = Sablier(0xabcd...);
uint256 streamId = 42;
uint256 senderAddress = 0xcdef...;
uint256 balance = sablier.balanceOf(streamId, senderAddress);
```

### Javascript

```javascript
const sablier = new ethers.Contract(0xabcd..., sablierABI, signerOrProvider);
const streamId = 42;
const senderAddress = 0xcdef...;
const balance = await sablier.balanceOf(streamId, senderAddress);
```

---

## Delta of

Returns either the difference between now and the start time of the stream OR between the stop time and the start time
of the stream, whichever is smaller. However, if the clock did not hit the start time of the stream, the value returned
is 0 instead.

```solidity
function deltaOf(uint256 streamId) view returns (uint256)‌
```

`streamId`: The id of the stream for which to query the delta. `RETURN`: The time delta in seconds.

### Solidity

```solidity
Sablier sablier = Sablier(0xabcd...);
uint256 streamId = 42;
uint256 delta = sablier.deltaOf(streamId);‌
```

### Ethers.js

```javascript
const sablier = new ethers.Contract(0xabcd..., sablierABI, signerOrProvider);
const streamId = 42;
const delta = await sablier.deltaOf(streamId);
```

---

## Error Table

The table below lists all possible reasons for reverting a contract call that creates, withdraws from or cancels a
stream. The "Id" column is just a counter used in this table - the smart contract does not yield error codes, just
strings.

| Number | Error | Reason |
| ------ | ------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| 1 | stream does not exist | The provided stream id does not point to a valid stream |
| 2 | caller is not the sender or the recipient of the stream | The contract call originates from an unauthorized third-party |
| 3 | SafeERC20: low-level call failed | Possibly insufficient allowance, but not necessarily so |
| 4 | stream to the zero address | Attempt to stream tokens to the [zero address](https://etherscan.io/address/0x0000000000000000000000000000000000000000) |
| 5 | stream to the contract itself | Attempt to stream tokens to the Sablier contract |
| 6 | stream to the caller | Happens when the caller attempts to stream tokens to herself |
| 7 | deposit is zero | Attempt to stream 0 tokens |
| 8 | start time before block.timestamp | Tokens cannot be streamed retroactively |
| 9 | stop time before the start time | Negative streaming is not allowed |
| 10 | deposit smaller than time delta | The deposit, measured in units of the token, is smaller than the time delta |
| 11 | deposit not multiple of time delta | The deposit has a non-zero remainder when divided by the time delta |
| 12 | amount is zero | Attempt to withdraw 0 tokens |
| 13 | amount exceeds the available balance | Attempt to withdraw more tokens than the available balance |
| 14 | recipient balance calculation error | Happens only when streaming an absurdly high number of tokens (close to 2^256) |

:::info

The contract call could revert with [no reason](https://vmexceptionwhileprocessingtransactionrevert.com/) provided. In
this case, you probably did not approve the Sablier contract to spend your token balance, although this is not
necessarily the case. Ping us on [Discord](https://discord.gg/bSwRCwWRsT) if you get stuck.

:::
166 changes: 166 additions & 0 deletions docs/contracts/v1/contracts/non-constant-functions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
---
id: non-constant-functions
title: Non-Constant Functions
sidebar_position: 2
---

## Create stream

The create stream function transfers the tokens into the Sablier smart contract, stamping the rules of the stream into
the blockchain. As soon as the chain clock hits the start time of the stream, a small portion of tokens starts getting
"transferred" from the sender to the recipient once every second.

We used scare quotes because what actually happens is not a transfer, but rather an abstract allocation of funds. Every
second, the in-contract allowance of the sender decreases. while the recipient's allocation increases, even if the
tokens are not transferred to the recipient. Actually transferring the tokens would be excessively expensive in terms of
gas costs.

```solidity
function createStream(address recipient, uint256 deposit, address tokenAddress, uint256 startTime, uint256 stopTime) returns (uint256)
```

- `msg.sender`: The account who funds the stream, and pays the recipient in real-time.
- `recipient`: The account toward which the tokens will be streamed.
- `deposit`: The amount of tokens to be streamed, in units of the streaming currency.
- `tokenAddress`: The address of the ERC-20 token to use as streaming currency.
- `startTime`: The unix timestamp for when the stream starts, in seconds.
- `stopTime`: The unix timestamp for when the stream stops, in seconds.
- `RETURN`: The stream's id as an unsigned integer on success, reverts on error.

:::caution

Before creating a stream, users must first [approve](https://eips.ethereum.org/EIPS/eip-20#approve) the Sablier contract
to access their token balance.

:::

:::warning

The transaction must be processed by the Ethereum blockchain before the start time of the stream, or otherwise the
contract will revert with a "start time before block.timestamp" message.

:::

### The Deposit Gotcha

The deposit must be a multiple of the difference between the stop time and the start time, or otherwise the contract
reverts with a "deposit not multiple of time delta" message. In practice, this means that you may not able to always use
exact amounts like 3,000. You may have to divide the fixed deposit by the time delta and subtract the remainder from the
initial number. Thus you may have to stream a value that is very, very close to the fixed deposit, but not quite it.

For example, if:

- The token has 18 decimals
- The time delta is 2592000 (30 days)

You will have to stream 2999999999999998944000 instead of 3000000000000000000000. The former divides evenly by 2592000,
but the latter doesn't.

### Solidity

```solidity
Sablier sablier = Sablier(0xabcd...); // get a handle for the Sablier contract
address recipient = 0xcdef...;
uint256 deposit = 2999999999999998944000; // almost 3,000, but not quite
uint256 startTime = block.timestamp + 3600; // 1 hour from now
uint256 stopTime = block.timestamp + 2592000 + 3600; // 30 days and 1 hour from now
Erc20 token = Erc20(0xcafe...); // get a handle for the token contract
token.approve(address(sablier), deposit); // approve the transfer
// the stream id is needed later to withdraw from or cancel the stream
uint256 streamId = sablier.createStream(recipient, deposit, address(token), startTime, stopTime);
```

### Ethers.js

```javascript
const sablier = new ethers.Contract(0xabcd..., sablierABI, signerOrProvider); // get a handle for the Sablier contract
const recipient = 0xcdef...;
const deposit = "2999999999999998944000"; // almost 3,000, but not quite
const now = Math.round(new Date().getTime() / 1000); // get seconds since unix epoch
const startTime = now + 3600; // 1 hour from now
const stopTime = now + 2592000 + 3600; // 30 days and 1 hour from now

const token = new ethers.Contract(0xcafe..., erc20ABI, signerOrProvider); // get a handle for the token contract
const approveTx = await token.approve(sablier.address, deposit); // approve the transfer
await approveTx.wait();

const createStreamTx = await sablier.createStream(recipient, deposit, token.address, startTime, stopTime);
await createStreamTx.wait();
```

---

## Withdraw from Stream

The withdraw from stream function transfers an amount of tokens from the Sablier contract to the recipient's account.
The withdrawn amount must be less than or equal to the available [balance](./constant-functions#balance-of). This
function can only be called by the sender or the recipient of the stream, not any third-party.

```solidity
function withdrawFromStream(uint256 streamId, uint256 amount) returns (bool);
```

- `streamId`: The id of the stream to withdraw tokens from.
- `amount`: The amount of tokens to withdraw.
- `RETURN`: True on success, reverts on error.

:::info

To be able to call this function, you have to wait until the clock goes past the start time of the stream.

:::

### Solidity

```solidity
Sablier sablier = Sablier(0xabcd...);
uint256 streamId = 42;
uint256 amount = 100;
require(sablier.withdrawFromStream(streamId, amount), "something went wrong");‌
```

### Ethers.js

```javascript
const sablier = new ethers.Contract(0xabcd..., sablierABI, signerOrProvider);
const streamId = 42;
const amount = 100;
const withdrawFromStreamTx = await sablier.withdrawFromStream(streamId, amount);
await withdrawFromStreamTx.wait();
```

---

## Cancel Stream

The cancel stream function revokes a previously created stream and returns the tokens back to the sender and/or the
recipient. If the chain clock did not hit the start time, all the tokens is returned to the sender. If the chain clock
did go past the start time, but not past the stop time, the sender and the recipient each get a pro-rata amount.
Finally, if the chain clock went past the stop time, all the tokens goes the recipient. This function can be called only
by the sender.

```solidity
function cancelStream(uint256 streamId) returns (bool);
```

- `streamId`: The id of the stream to cancel.
- `RETURN`: True on success, reverts on error.

### Solidity

```solidity
Sablier sablier = Sablier(0xabcd...);
uint256 streamId = 42;
require(sablier.cancelStream(streamId), "something went wrong");
```

### Ethers.js

```javascript
const sablier = new ethers.Contract(0xabcd..., sablierABI, signerOrProvider);
const streamId = 42;
const cancelStreamTx = await sablier.cancelStream(streamId);
await cancelStreamTx.wait();
```
5 changes: 5 additions & 0 deletions docs/contracts/v1/guides/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"collapsed": true,
"label": "Guides",
"position": 2
}
Loading

0 comments on commit f01ea9c

Please sign in to comment.