From 29fdc7561db676a019d770c29d4034efba575704 Mon Sep 17 00:00:00 2001 From: Andrei Vlad Birgaoanu Date: Tue, 4 Nov 2025 19:24:36 +0200 Subject: [PATCH 1/3] feat: add fee in the withdraw examples --- .../flow/examples/04-stream-management.mdx | 16 ++++++++++++---- docs/guides/flow/examples/05-batchable.mdx | 7 +++++++ .../examples/stream-management/02-withdraw.mdx | 12 +++++++++--- 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/docs/guides/flow/examples/04-stream-management.mdx b/docs/guides/flow/examples/04-stream-management.mdx index e9b03f0a..9781ed34 100644 --- a/docs/guides/flow/examples/04-stream-management.mdx +++ b/docs/guides/flow/examples/04-stream-management.mdx @@ -84,13 +84,21 @@ There are two withdrawal functions: 2. [`withdrawMax`](/reference/flow/contracts/contract.SablierFlow#withdrawmax): withdraws the entire withdrawable amount of tokens. +:::note + +The `withdraw` functions requires a fee. Make sure to send the correct amount in `msg.value`, as shown below. + +::: + ```solidity -function withdraw(uint256 streamId) external { - FLOW.withdraw({ streamId: streamId, to: address(0xCAFE), amount: 2.71828e18 }); +function withdraw(uint256 streamId) external payable { + uint256 fee = FLOW.calculateMinFeeWei(streamId); + FLOW.withdraw{ value: fee }({ streamId: streamId, to: address(0xCAFE), amount: 2.71828e18 }); } -function withdrawMax(uint256 streamId) external { - FLOW.withdrawMax({ streamId: streamId, to: address(0xCAFE) }); +function withdrawMax(uint256 streamId) external payable { + uint256 fee = FLOW.calculateMinFeeWei(streamId); + FLOW.withdrawMax{ value: fee }({ streamId: streamId, to: address(0xCAFE) }); } ``` diff --git a/docs/guides/flow/examples/05-batchable.mdx b/docs/guides/flow/examples/05-batchable.mdx index 20ea0adf..97541ccd 100644 --- a/docs/guides/flow/examples/05-batchable.mdx +++ b/docs/guides/flow/examples/05-batchable.mdx @@ -101,6 +101,13 @@ Try to implement the following ideas using `batch` function: - Void and Withdraw Max - Multiple Withdraw Max +:::note + +If you include any `withdraw` function in your batch, keep in mind that it requires a fee. Make sure to send the correct +amount in `msg.value`, as shown below. + +::: + Below, you will find the full code for it. ## Other ideas diff --git a/docs/guides/lockup/examples/stream-management/02-withdraw.mdx b/docs/guides/lockup/examples/stream-management/02-withdraw.mdx index 8beb87b9..907df61d 100644 --- a/docs/guides/lockup/examples/stream-management/02-withdraw.mdx +++ b/docs/guides/lockup/examples/stream-management/02-withdraw.mdx @@ -37,8 +37,14 @@ To call any of these functions, you need to have created a stream. If you don't [previous guide](/guides/lockup/examples/create-stream/lockup-linear) and create a stream with a brief duration, assigning the `StreamManagement` contract as the recipient. Then, you can use the `withdraw` function like this: +:::note + +The `withdraw` functions requires a fee. Make sure to send the correct amount in `msg.value`, as shown below. + +::: + - {`https://github.com/sablier-labs/evm-examples/blob/main/lockup/StreamManagement.sol#L20-L22`} + {`https://github.com/sablier-labs/evm-examples/blob/main/lockup/StreamManagement.sol#L20-L23`} In this example, the withdrawal address and withdrawal amount are hard-coded for demonstration purposes. However, in a @@ -50,7 +56,7 @@ In addition to the `withdraw` function, there is the `withdrawMax` function, whi withdrawable amount of tokens at the time of invocation: - {`https://github.com/sablier-labs/evm-examples/blob/main/lockup/StreamManagement.sol#L25-L27`} + {`https://github.com/sablier-labs/evm-examples/blob/main/lockup/StreamManagement.sol#L26-L29`} What `withdrawMax` does is call the @@ -63,5 +69,5 @@ same time, transfer the NFT to another address. Lastly, there is the `withdrawMultiple` function, with which you can use to withdraw from multiple streams at once: - {`https://github.com/sablier-labs/evm-examples/blob/main/lockup/StreamManagement.sol#L30-L32`} + {`https://github.com/sablier-labs/evm-examples/blob/main/lockup/StreamManagement.sol#L32-L44`} From 7d5b68b7c032ffadf4d2343745531565e77faf13 Mon Sep 17 00:00:00 2001 From: Andrei Vlad Birgaoanu Date: Tue, 4 Nov 2025 19:30:40 +0200 Subject: [PATCH 2/3] feat: add requirement in flow's withdraw --- docs/reference/flow/contracts/contract.SablierFlow.md | 1 + .../flow/contracts/interfaces/interface.ISablierFlow.md | 1 + 2 files changed, 2 insertions(+) diff --git a/docs/reference/flow/contracts/contract.SablierFlow.md b/docs/reference/flow/contracts/contract.SablierFlow.md index 9c9c96dc..81bcae29 100644 --- a/docs/reference/flow/contracts/contract.SablierFlow.md +++ b/docs/reference/flow/contracts/contract.SablierFlow.md @@ -764,6 +764,7 @@ Emits a {Transfer}, {WithdrawFromFlowStream} and {MetadataUpdate} event. Notes: - `to` must not be the zero address. - `to` must be the recipient if `msg.sender` is not the stream's recipient or an approved third party. - `amount` must be greater than zero and must not exceed the withdrawable amount. +- `msg.value` must be greater than or equal to the minimum fee in wei for the stream's sender. ```solidity function withdraw( diff --git a/docs/reference/flow/contracts/interfaces/interface.ISablierFlow.md b/docs/reference/flow/contracts/interfaces/interface.ISablierFlow.md index c956ea75..9809d469 100644 --- a/docs/reference/flow/contracts/interfaces/interface.ISablierFlow.md +++ b/docs/reference/flow/contracts/interfaces/interface.ISablierFlow.md @@ -595,6 +595,7 @@ Emits a {Transfer}, {WithdrawFromFlowStream} and {MetadataUpdate} event. Notes: - `to` must not be the zero address. - `to` must be the recipient if `msg.sender` is not the stream's recipient or an approved third party. - `amount` must be greater than zero and must not exceed the withdrawable amount. +- `msg.value` must be greater than or equal to the minimum fee in wei for the stream's sender. ```solidity function withdraw(uint256 streamId, address to, uint128 amount) external payable; From 568121cb41c414562b6b09d30fc9ad53ce5dfee6 Mon Sep 17 00:00:00 2001 From: smol-ninja Date: Tue, 4 Nov 2025 22:42:03 +0000 Subject: [PATCH 3/3] use codeblocks --- .../flow/examples/04-stream-management.mdx | 102 ++++++------------ 1 file changed, 31 insertions(+), 71 deletions(-) diff --git a/docs/guides/flow/examples/04-stream-management.mdx b/docs/guides/flow/examples/04-stream-management.mdx index 9781ed34..e6adb9d4 100644 --- a/docs/guides/flow/examples/04-stream-management.mdx +++ b/docs/guides/flow/examples/04-stream-management.mdx @@ -23,25 +23,21 @@ please note the following: Declare the Solidity version used to compile the contract: -```solidity -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity >=0.8.22; -``` + + {`https://github.com/sablier-labs/evm-examples/blob/main/flow/FlowStreamManager.sol#L1-L2`} + Import the relevant symbols from `@sablier/flow` and `@prb/math`: -```solidity -import { ud21x18 } from "@prb/math/src/UD21x18.sol"; -import { ISablierFlow } from "@sablier/flow/src/interfaces/ISablierFlow.sol"; -``` + + {`https://github.com/sablier-labs/evm-examples/blob/main/flow/FlowStreamManager.sol#L4-L5`} + Declare the contract and add the Flow address as a constant: -```solidity -contract FlowStreamManager { - ISablierFlow public constant FLOW = ISablierFlow(0x7a86d3e6894f9c5B5f25FFBDAaE658CFc7569623); -} -``` + + {`https://github.com/sablier-labs/evm-examples/blob/main/flow/FlowStreamManager.sol#L7-L9`} + @@ -62,15 +58,9 @@ There are three deposit functions: 2. [`depositAndPause`](/reference/flow/contracts/contract.SablierFlow#depositandpause): deposits an amount of tokens and then pauses the stream. -```solidity -function deposit(uint256 streamId, uint256 amount) external { - FLOW.deposit(streamId, amount); -} - -function depositAndPause(uint256 streamId) external { - FLOW.depositAndPause(streamId, 3.14159e18); -} -``` + + {`https://github.com/sablier-labs/evm-examples/blob/main/flow/FlowStreamManager.sol#L15-L21`} + ## Withdraw @@ -90,37 +80,25 @@ The `withdraw` functions requires a fee. Make sure to send the correct amount in ::: -```solidity -function withdraw(uint256 streamId) external payable { - uint256 fee = FLOW.calculateMinFeeWei(streamId); - FLOW.withdraw{ value: fee }({ streamId: streamId, to: address(0xCAFE), amount: 2.71828e18 }); -} - -function withdrawMax(uint256 streamId) external payable { - uint256 fee = FLOW.calculateMinFeeWei(streamId); - FLOW.withdrawMax{ value: fee }({ streamId: streamId, to: address(0xCAFE) }); -} -``` + + {`https://github.com/sablier-labs/evm-examples/blob/main/flow/FlowStreamManager.sol#L51-L59`} + ## Adjust Rate per Second Adjusting the rate per second means changing the amount of tokens that is streamed each second. -```solidity -function adjustRatePerSecond(uint256 streamId) external { - FLOW.adjustRatePerSecond({ streamId: streamId, newRatePerSecond: ud21x18(0.0001e18) }); -} -``` + + {`https://github.com/sablier-labs/evm-examples/blob/main/flow/FlowStreamManager.sol#L11-L13`} + ## Pause Pausing a stream means setting the rate per second to zero, which means no more streaming. -```solidity -function pause(uint256 streamId) external { - FLOW.pause(streamId); -} -``` + + {`https://github.com/sablier-labs/evm-examples/blob/main/flow/FlowStreamManager.sol#L23-L25`} + ## Restart @@ -130,15 +108,9 @@ There are two restart functions: 2. [`restartAndDeposit`](/reference/flow/contracts/contract.SablierFlow#restartanddeposit): restarts a stream followed by depositing an amount of tokens into it. -```solidity -function restart(uint256 streamId) external { - FLOW.restart({ streamId: streamId, ratePerSecond: ud21x18(0.0001e18) }); -} - -function restartAndDeposit(uint256 streamId) external { - FLOW.restartAndDeposit({ streamId: streamId, ratePerSecond: ud21x18(0.0001e18), amount: 2.71828e18 }); -} -``` + + {`https://github.com/sablier-labs/evm-examples/blob/main/flow/FlowStreamManager.sol#L39-L45`} + ## Refund @@ -151,35 +123,23 @@ There are three refund functions: 3. [`refundMax`](/reference/flow/contracts/contract.SablierFlow#refundmax): refunds the entire refundable amount of tokens. -```solidity -function refund(uint256 streamId) external { - FLOW.refund({ streamId: streamId, amount: 1.61803e18 }); -} - -function refundAndPause(uint256 streamId) external { - FLOW.refundAndPause({ streamId: streamId, amount: 1.61803e18 }); -} - -function refundMax(uint256 streamId) external { - FLOW.refundMax(streamId); -} -``` + + {`https://github.com/sablier-labs/evm-examples/blob/main/flow/FlowStreamManager.sol#L27-L37`} + ## Void Voiding a stream means permanently stopping it from streaming any tokens. This is slightly different from pausing a stream because it also sets the stream's uncovered debt to zero. -```solidity -function void(uint256 streamId) external { - FLOW.void(streamId); -} -``` + + {`https://github.com/sablier-labs/evm-examples/blob/main/flow/FlowStreamManager.sol#L47-L49`} + ## Full code Below you can see the complete `FlowStreamManager` contract: - + {`https://github.com/sablier-labs/evm-examples/blob/main/flow/FlowStreamManager.sol`}