diff --git a/docs/concepts/flow/01-overview.md b/docs/concepts/flow/01-overview.md
index 2de86489..b3a371a8 100644
--- a/docs/concepts/flow/01-overview.md
+++ b/docs/concepts/flow/01-overview.md
@@ -53,7 +53,7 @@ Total debt is the amount of tokens owed to the recipient. This value is further
### Snapshot debt and Snapshot time
A snapshot is an event during which snapshot debt and snapshot time of a Flow stream are updated. **Snapshot debt** is
-the debt accumulated since the previous snapshot. The UNIX timestamp at which snapshot debt is updated is called
+the debt accumulated until the previous snapshot. The UNIX timestamp at which snapshot debt is updated is called
**Snapshot time**.
At snapshot, the following operations are taking place:
@@ -67,6 +67,14 @@ rps \cdot (\text{block.timestamp} - \text{snapshot time})}_\text{ongoing debt}
\text{snapshot time} = \text{block.timestamp}
```
+### Ongoing debt
+
+Ongoing debt is the debt accumulated since the previous snapshot. It is calculated as the following:
+
+```math
+\text{ongoing debt} = rps \cdot (\text{block.timestamp} - \text{snapshot time})
+```
+
Therefore, at any point in time, total debt can also be defined as:
```math
diff --git a/docs/concepts/flow/02-statuses.md b/docs/concepts/flow/02-statuses.md
index a0efc994..b70cfce8 100644
--- a/docs/concepts/flow/02-statuses.md
+++ b/docs/concepts/flow/02-statuses.md
@@ -27,37 +27,83 @@ A stream can have the following characteristics:
| Solvent | `STREAMING_SOLVENT`, `PAUSED_SOLVENT`, `VOIDED` | Total debt not exceeding the stream balance. |
| Insolvent | `STREAMING_INSOLVENT`, `PAUSED_INSOLVENT` | Total debt exceeding the stream balance. |
-## Diagram
+## State transitions
The following diagram illustrates the statuses and the allowed transitions between them:
```mermaid
flowchart LR
- N[NULL]
- V[VOIDED]
+ N(NULL)
+ V(VOIDED)
- subgraph Paused
+ subgraph PAUSED
direction RL
- PS[PAUSED_SOLVENT]
- PI[PAUSED_INSOLVENT]
+ PS(SOLVENT)
+ PI(INSOLVENT)
PI -- "deposit" --> PS
end
- subgraph Streaming
+ subgraph STREAMING
direction LR
- SS[STREAMING_SOLVENT]
- SI[STREAMING_INSOLVENT]
+ SS(SOLVENT)
+ SI(INSOLVENT)
SI -- "deposit" --> SS
SS -- "time" --> SI
end
- Streaming -- pause --> Paused
- Streaming -- void --> V
- Paused -- restart --> Streaming
- Paused -- void --> V
+ STREAMING -- pause --> PAUSED
+ STREAMING -- void --> V
+ PAUSED -- restart --> STREAMING
+ PAUSED -- void --> V
- N -- create (rps > 0) --> Streaming
- N -- create (rps = 0) --> Paused
+ N -- create (rps > 0) --> STREAMING
+ N -- create (rps = 0) --> PAUSED
+```
+
+## Functions Statuses Interaction
+
+### NULL stream
+
+```mermaid
+flowchart LR
+ CR[CREATE] --> NULL((NULL))
+```
+
+### STREAMING stream
+
+```mermaid
+flowchart TD
+ STR((STREAMING))
+
+ ADJRPS[ADJUST_RPS] --> STR
+ DP[DEPOSIT] --> STR
+ RFD[REFUND] --> STR
+ PS[PAUSE] --> STR
+ VD[VOID] --> STR
+ WTD[WITHDRAW] --> STR
+```
+
+### PAUSED stream
+
+```mermaid
+flowchart TD
+ PSED((PAUSED))
+
+ DP([DEPOSIT]) --> PSED
+ RFD([REFUND]) --> PSED
+ RST([RESTART]) --> PSED
+ VD([VOID]) --> PSED
+ WTD([WITHDRAW]) --> PSED
+```
+
+### VOIDED stream
+
+```mermaid
+flowchart LR
+ VOID((VOIDED))
+
+ RFD([REFUND]) --> VOID
+ WTD([WITHDRAW]) --> VOID
```
## Q&A
@@ -78,3 +124,7 @@ can pause it.
A: Both sender and recipient can void the stream. This is especially useful when either party wants to stop the stream
immediately. Once a stream is voided, it cannot be restarted. If there is uncovered debt, it will be reset to 0. So to
ensure that your recipient does not lose on any streamed amount, you can deposit into the stream before voiding it.
+
+```
+
+```
diff --git a/docs/concepts/lockup/06-statuses.md b/docs/concepts/lockup/06-statuses.md
index 89d9cd71..43d61aac 100644
--- a/docs/concepts/lockup/06-statuses.md
+++ b/docs/concepts/lockup/06-statuses.md
@@ -25,7 +25,7 @@ A stream status can have one out of two "temperatures":
| Warm | Pending, Streaming | The passage of time alone can change the status. |
| Cold | Settled, Canceled, Depleted | The passage of time alone cannot change the status. Only a user action can do this. |
-## Diagram
+## State transitions
The following diagram illustrates the statuses and the allowed transitions between them:
diff --git a/docs/concepts/lockup/07-hooks.md b/docs/concepts/lockup/07-hooks.md
index 31de4770..e8d073c5 100644
--- a/docs/concepts/lockup/07-hooks.md
+++ b/docs/concepts/lockup/07-hooks.md
@@ -32,18 +32,34 @@ If the recipient contract is not on the allowlist, the hooks will not be execute
:::
+### Cancel hook
+
+```mermaid
+sequenceDiagram
+ actor Sender
+
+ Sender ->> SablierLockup: cancel()
+ SablierLockup -->> Recipient: onSablierLockupCancel()
+ Recipient -->> SablierLockup: return selector
+ SablierLockup -->> Sender: transfer unstreamed tokens
+ break if hook reverts
+ Recipient -->> SablierLockup: ❌ tx fail
+ end
+```
+
+### Withdraw hook
+
```mermaid
-flowchart LR
- S((Sender))
- A((Anyone))
- subgraph Core
- L[SablierLockup]
+sequenceDiagram
+ actor Anyone
+
+ Anyone ->> SablierLockup: withdraw()
+ SablierLockup -->> Recipient: onSablierLockupWithdraw()
+ Recipient -->> SablierLockup: return selector
+ SablierLockup -->> Recipient: transfer streamed tokens
+ break if hook reverts
+ Recipient -->> SablierLockup: ❌ tx fail
end
- R((Recipient))
- S -- "cancel" --> L
- L -- "onSablierLockupCancel" --> R
- A -- "withdraw" --> L
- L -- "onSablierLockupWithdraw" --> R
```
## Next steps
diff --git a/docs/reference/flow/01-diagrams.md b/docs/reference/flow/01-diagrams.md
index d0f56329..98902386 100644
--- a/docs/reference/flow/01-diagrams.md
+++ b/docs/reference/flow/01-diagrams.md
@@ -4,6 +4,21 @@ sidebar_position: 1
title: "Diagrams"
---
+## Abbreviations
+
+| Abbreviation | Full name | Description |
+| ------------ | --------------- | ----------------------------------------------------------- |
+| bal | Stream balance | Balance of the stream |
+| cd | Covered debt | Portion of the total debt covered by the stream balance |
+| elt | Elapsed time | Time elapsed in seconds since the last snapshot |
+| od | Ongoing debt | Debt accumulated since the last snapshot |
+| now | Current time | Same as `block.timestamps` |
+| rps | Rate per second | Rate at which tokens are streamed per second |
+| sd | Snapshot debt | Debt accumulated until the last snapshot |
+| st | Snapshot time | Time of the last snapshot |
+| td | Total debt | Sum of sd and od, also same as sum of cd and ud |
+| ud | Uncovered debt | Portion of the total debt not covered by the stream balance |
+
## Flow Storage Layout
Each Flow contract is a singleton that stores all streams created by that contract's users. The following diagrams
@@ -13,10 +28,10 @@ provide insight into the storage layout. To see the list of all storage variable
```mermaid
flowchart LR
storage[(Storage)]
- bal([Balance - bal])
- rps([RatePerSecond - rps])
- sd([SnapshotDebtScaled - sd])
- st([Snapshot Time - st])
+ bal([bal])
+ rps([rps])
+ sd([sd])
+ st([st])
storage --> bal
storage --> rps
@@ -24,29 +39,82 @@ flowchart LR
storage --> st
```
-## Token Balance Actions
+## Token Flows
+
+The following three functions lead to tokens flow in and out of a stream:
+
+### Deposit
+
+Anyone can deposit into a stream.
```mermaid
-flowchart LR
- erc_transfers[(ERC20 Transfer Actions)]
- dep([Deposit - add])
- ref([Refund - remove])
- wtd([Withdraw - remove])
-
- erc_transfers --> dep
- erc_transfers --> ref
- erc_transfers --> wtd
+sequenceDiagram
+ actor Anyone
+
+ Anyone ->> Flow: deposit()
+ Anyone -->> Flow: Transfer tokens
```
-$~$
+### Refund
+
+Only sender can refund from the stream that he created.
+
+```mermaid
+sequenceDiagram
+ actor Sender
+
+ Sender ->> Flow: refund()
+ Flow -->> Sender: Transfer unstreamed tokens
+```
+
+### Withdraw
+
+Anyone can call withdraw on a stream as long as `to` address matches the recipient. If recipient/operator is calling
+withdraw on a stream, they can choose to withdraw to any address.
+
+```mermaid
+sequenceDiagram
+ actor Anyone
+
+ Anyone ->> Flow: withdraw()
+ activate Flow
+ Create actor Recipient
+ Flow -->> Recipient: Transfer streamed tokens
+ deactivate Flow
+
+ Recipient ->> Flow: withdraw()
+ activate Flow
+ Create actor toAddress
+ Flow -->> toAddress: Transfer streamed tokens
+ deactivate Flow
+```
## Debts
+### Covered debt
+
+```mermaid
+flowchart TD
+ di0{ }:::blue0
+ di1{ }:::blue0
+ cd([cd])
+ res_0([0 ])
+ res_bal([bal])
+ res_sum([td])
+
+
+ cd --> di0
+ di0 -- "bal = 0" --> res_0
+ di0 -- "bal > 0" --> di1
+ di1 -- "ud > 0" --> res_bal
+ di1 -- "ud = 0" --> res_sum
+```
+
### Ongoing Debt
```mermaid
flowchart TD
-rca([Ongoing Debt - od])
+rca([od])
di0{ }
di1{ }
res_00([0 ])
@@ -62,15 +130,10 @@ di1 -- "now > st" --> res_rca
### Uncovered Debt
-**Notes:** A non-zero uncovered debt implies:
-
-1. `bal < sd` when the status is `PAUSED`
-2. `bal < sd + od` when the status is `STREAMING`
-
```mermaid
flowchart TD
di0{ }:::red1
- sd([Uncovered Debt - ud])
+ sd([ud])
res_sd(["td - bal"])
res_zero([0])
@@ -79,34 +142,25 @@ flowchart TD
di0 -- "bal >= td" --> res_zero
```
-### Covered debt
+### Total Debt
```mermaid
flowchart TD
- di0{ }:::blue0
- di1{ }:::blue0
- di2{ }:::blue0
- cd([Covered Debt - cd])
- res_0([0 ])
- res_bal([bal])
- res_sd([sd])
- res_sum([td])
-
+rca([td])
+di0{ }
+res_00([sd ])
+res_01(["sd + od"])
- cd --> di0
- di0 -- "bal = 0" --> res_0
- di0 -- "bal > 0" --> di1
- di1 -- "ud > 0" --> res_bal
- di1 -- "ud = 0" --> di2
- di2 -- "paused" --> res_sd
- di2 -- "streaming" --> res_sum
+rca --> di0
+di0 -- "rps == 0" --> res_00
+di0 -- "rps > 0" --> res_01
```
-### Refundable Amount
+## Refundable Amount
```mermaid
flowchart TD
- ra([Refundable Amount - ra])
+ ra([Refundable Amount])
res_ra([bal - cd])
ra --> res_ra
```
diff --git a/docs/reference/flow/03-access-control.md b/docs/reference/flow/03-access-control.md
index c800dd57..5e0b6235 100644
--- a/docs/reference/flow/03-access-control.md
+++ b/docs/reference/flow/03-access-control.md
@@ -32,3 +32,123 @@ The table below offers a quick overview of the access control for each action th
| Withdraw to any address | ❌ | ✅ | ❌ |
| Withdraw to recipient | ✅ | ✅ | ✅ |
| Void | ✅ | ✅ | ❌ |
+
+## Adjust rate per second
+
+Only the sender can adjust the rate per second of a stream.
+
+```mermaid
+sequenceDiagram
+ actor Sender
+
+ Sender ->> Flow: adjustRatePerSecond()
+ Flow -->> Flow: update rps
+```
+
+## Create stream
+
+```mermaid
+sequenceDiagram
+ actor Sender
+
+ Sender ->> Flow: create()
+ Create actor Recipient
+ Flow -->> Recipient: mint NFT
+```
+
+## Deposit into a stream
+
+Anyone can deposit into a stream.
+
+```mermaid
+sequenceDiagram
+ actor Anyone
+
+ Anyone ->> ERC20: approve()
+ Anyone ->> Flow: deposit()
+ Flow ->> ERC20: transferFrom()
+ Anyone -->> Flow: Transfer tokens
+```
+
+## Pause
+
+Only the sender can pause a stream.
+
+```mermaid
+sequenceDiagram
+ actor Sender
+
+ Sender ->> Flow: pause()
+ Flow -->> Flow: set rps = 0
+```
+
+## Refund from a stream
+
+Only the sender can refund from a stream.
+
+```mermaid
+sequenceDiagram
+ actor Sender
+
+ Sender ->> Flow: refund()
+ Flow ->> ERC20: transfer()
+ Flow -->> Sender: Transfer unstreamed tokens
+```
+
+## Restarting a stream
+
+Only the sender can restart a stream.
+
+```mermaid
+sequenceDiagram
+ actor Sender
+
+ Sender ->> Flow: restart()
+ Flow -->> Flow: set rps > 0
+```
+
+## Voiding a stream
+
+Both Sender and Recipient can void a stream.
+
+```mermaid
+ sequenceDiagram
+ actor Sender
+
+ Sender ->> Flow: void()
+ activate Flow
+ Flow -->> Flow: set rps = 0,
+ Flow -->> Flow: set st = now & sd = cd
+ deactivate Flow
+
+ actor Recipient
+ Recipient ->> Flow: void()
+ activate Flow
+ Flow -->> Flow: set rps = 0
+ Flow -->> Flow: set st = now & sd = cd
+ deactivate Flow
+```
+
+## Withdraw from a stream
+
+Anyone can call withdraw on a stream as long as `to` address matches the recipient. If recipient/operator is calling
+withdraw on a stream, they can choose to withdraw to any address.
+
+```mermaid
+sequenceDiagram
+ actor Anyone
+
+ Anyone ->> Flow: withdraw()
+ activate Flow
+ Flow ->> ERC20: transfer()
+ Create actor Recipient
+ Flow -->> Recipient: Transfer tokens
+ deactivate Flow
+
+ Recipient ->> Flow: withdraw()
+ activate Flow
+ Flow ->> ERC20: transfer()
+ Create actor Any Address
+ Flow -->> Any Address : Transfer tokens
+ deactivate Flow
+```
diff --git a/docs/reference/lockup/01-diagrams.md b/docs/reference/lockup/01-diagrams.md
index dc71c15a..fff540c7 100644
--- a/docs/reference/lockup/01-diagrams.md
+++ b/docs/reference/lockup/01-diagrams.md
@@ -144,23 +144,22 @@ flowchart LR;
A typical Airstream campaign creation flow looks like the following:
```mermaid
-flowchart LR
- MSF[(MerkleLockupFactory Contract)]
- MS[(MerkleLockup Contract)]
- S[Campaign creator] -- "createMerkleLL" --> MSF
- MSF -- "create2" --> MS
+sequenceDiagram
+ actor Campaign creator
+
+ Campaign creator ->> MerkleLockupFactory: createMerkleLL()
+ MerkleLockupFactory -->> MerkleLockup: Deploy a new contract
```
And this is how the claim flow looks like for recipients:
```mermaid
-flowchart LR
- R1[Recipient]
- MS[(MerkleLockup Contract)]
- LL[(LockupLinear Contract)]
- R1 -- "claim" --> MS
- MS -- "createWithDurations" --> LL
- LL -- "Transfer NFT" --> R1
+sequenceDiagram
+ actor Airdrop recipient
+
+ Airdrop recipient ->> MerkleLockup: claim()
+ MerkleLockup -->> LockupLinear: Create vesting stream
+ LockupLinear -->> Airdrop recipient: Mint Stream NFT
```
For campaign admins, we offer `clawback` functionality which can be used to retrieve unclaimed funds after expiration.
@@ -169,9 +168,9 @@ There is also a grace period that ends 7 days after the first claim is made. Dur
transfer of funds.
```mermaid
-flowchart LR
- A[Campaign Admin]
- MS[(MerkleLockup Contract)]
- A -- "clawback" --> MS
- MS -- "unclaimed funds" --> A
+sequenceDiagram
+ actor Campaign creator
+
+ Campaign creator ->> MerkleLockup: clawback()
+ MerkleLockup -->> Campaign creator: Transfer unclaimed tokens
```
diff --git a/docs/reference/lockup/04-access-control.md b/docs/reference/lockup/04-access-control.md
index 9c95b0c8..024e0cbb 100644
--- a/docs/reference/lockup/04-access-control.md
+++ b/docs/reference/lockup/04-access-control.md
@@ -37,14 +37,23 @@ The table below offers a quick overview of the access control for each action th
Either the recipient or an approved operator can burn the NFT associated with a stream.
```mermaid
-flowchart LR;
- recipient((Recipient));
- operator((Operator));
- nft[(NFT)];
-
- recipient -- burn -->nft;
- recipient -- approve -->operator;
- operator -- burn -->nft;
+sequenceDiagram
+ actor Recipient
+
+ Recipient ->> Lockup: burn()
+ Recipient -->> address(0): Transfer stream NFT
+```
+
+#### With Operator:
+
+```mermaid
+sequenceDiagram
+ actor Recipient
+ actor Operator
+
+ Recipient ->> Lockup: approve(operator)
+ Operator ->> Lockup: burn()
+ Recipient -->> address(0): Transfer stream NFT
```
## Cancel
@@ -52,10 +61,11 @@ flowchart LR;
Only the sender can cancel a stream.
```mermaid
-flowchart LR;
- sender((Sender));
- stream[(Stream)];
- sender -- cancel -->stream;
+sequenceDiagram
+ actor Sender
+
+ Sender ->> Lockup: cancel()
+ Lockup -->> Sender: Transfer unvested tokens
```
## Cancel Multiple
@@ -63,11 +73,11 @@ flowchart LR;
Only the sender can cancel multiple streams.
```mermaid
-flowchart LR;
- sender((Sender));
- streams[(Multiple Streams)];
+sequenceDiagram
+ actor Sender
- sender -- cancelMultiple -->streams;
+ Sender ->> Lockup: cancelMultiple()
+ Lockup -->> Sender: Transfer unvested tokens from multiple streams
```
## Renounce
@@ -75,10 +85,10 @@ flowchart LR;
Only the sender can renounce a stream.
```mermaid
-flowchart LR;
- sender((Sender));
- stream[(Stream)];
- sender -- renounce -->stream;
+sequenceDiagram
+ actor Sender
+
+ Sender ->> Lockup: renounce()
```
## Transfer NFT
@@ -88,14 +98,25 @@ Either the recipient or an approved operator can transfer the NFT associated wit
- Only if the stream is transferable.
```mermaid
-flowchart LR;
- recipient((Recipient));
- operator((Operator));
- nft[(NFT)];
-
- recipient -- transfer -->nft;
- recipient -- approve -->operator;
- operator -- transfer -->nft;
+sequenceDiagram
+ actor Recipient
+
+ Recipient ->> Lockup: transfer(toAddress)
+ Create actor toAddress
+ Recipient -->> toAddress: Transfer NFT
+```
+
+#### With Operator:
+
+```mermaid
+sequenceDiagram
+ actor Recipient
+ actor Operator
+
+ Recipient ->> Lockup: approve(operator)
+ Operator ->> Lockup: transfer(toAddress)
+ Create actor toAddress
+ Recipient -->> toAddress: Transfer NFT
```
## Withdraw Multiple
@@ -103,20 +124,16 @@ flowchart LR;
Anybody can withdraw tokens from multiple streams to the recipients of each stream.
```mermaid
-flowchart LR;
- public((Public));
- recipient((Recipient));
- operator((Operator));
- sender((Sender));
- streams[(Stream)];
- toAddress[Recipient address];
-
- public -- withdrawMultiple --> streams;
- sender -- withdrawMultiple --->streams;
- recipient -- withdrawMultiple --->streams
- recipient -- approve -->operator;
- operator -- withdrawMultiple -->streams;
- streams -- tokens --> toAddress;
+sequenceDiagram
+ actor Anyone
+
+ Anyone ->> Lockup: withdrawMultiple()
+ Create actor getRecipient(1)
+ Lockup -->> getRecipient(1): Transfer vested tokens from stream 1
+ Create actor getRecipient(2)
+ Lockup -->> getRecipient(2): Transfer vested tokens from stream 2
+ Create actor getRecipient(3)
+ Lockup -->> getRecipient(3): Transfer vested tokens from stream 3
```
## Withdraw to Any Address
@@ -124,16 +141,25 @@ flowchart LR;
The tokens in a stream can be withdrawn to any address only by the recipient or an approved third party.
```mermaid
-flowchart LR;
- recipient((Recipient));
- operator((Operator));
- stream[(Stream)];
- toAddress[Any address];
-
- recipient -- withdraw -->stream;
- recipient -- approve -->operator;
- operator -- withdraw -->stream;
- stream -- tokens --> toAddress;
+sequenceDiagram
+ actor Recipient
+
+ Recipient ->> Lockup: withdraw(toAddress)
+ Create actor toAddress
+ Lockup -->> toAddress: Transfer vested tokens
+```
+
+#### With Operator:
+
+```mermaid
+sequenceDiagram
+ actor Recipient
+ actor Operator
+
+ Recipient ->> Lockup: approve(operator)
+ Operator ->> Lockup: withdraw(toAddress)
+ Create actor toAddress
+ Lockup -->> toAddress: Transfer vested tokens
```
## Withdraw to Recipient
@@ -142,18 +168,10 @@ The tokens in a stream can be withdrawn to the recipient by anyone including the
party.
```mermaid
-flowchart LR;
- public((Public caller));
- recipient((Recipient));
- operator((Operator));
- sender((Sender));
- stream[(Stream)];
- toAddress[Recipient address];
-
- public -- withdraw ----> stream;
- sender -- withdraw --->stream;
- recipient -- withdraw -->stream;
- recipient -- approve -->operator;
- operator -- withdraw -->stream;
- stream -- tokens --> toAddress;
+sequenceDiagram
+ actor Anyone
+
+ Anyone ->> Lockup: withdraw(recipient)
+ Create actor Recipient
+ Lockup -->> Recipient: Transfer vested tokens
```