Skip to main content

Batching Functions

A neat feature of Sablier Flow is the ability to batch multiple function calls into a single transaction. This is made possible by the Batch contract, which is inherited by SablierFlow. With this, you can efficiently batch multiple function calls in a single transaction.

caution

The code in this guide is not production-ready, and is implemented in a simplistic manner for the purpose of learning.

Set up a contract

Declare the Solidity version used to compile the contract:

pragma solidity >=0.8.22;

Import the relevant symbols:

import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { ud21x18, UD21x18 } from "@prb/math/src/UD21x18.sol";
import { ud60x18 } from "@prb/math/src/UD60x18.sol";
import { Broker, ISablierFlow } from "@sablier/flow/src/interfaces/ISablierFlow.sol";

Create a contract called FlowBatchable, and declare a constant USDC of type IERC20 and a constant FLOW of type ISablierFlow:

contract FlowBatchable {
IERC20 public constant USDC = IERC20(0xf08A50178dfcDe18524640EA6618a1f965821715);
ISablierFlow public constant FLOW = ISablierFlow(0x3a1beA13A8C24c0EA2b8fAE91E4b2762A59D7aF5);
}

In the code above, the contract addresses are hard-coded for demonstration purposes. However, in production, you would likely use input parameters to allow flexibility in changing the addresses.

Also, these addresses are deployed on Sepolia. If you need to work with a different chain, Flow addresses can be obtained from the Deployment Addresses page.

Create multiple streams

One of the most useful features achieved by batch is the ability to create multiple streams in a single transaction. Let's focus on it in this example.

Define a function that creates multiple streams and returns their respective stream IDs:

function createMultiple() external returns (uint256[] memory streamIds) {
// ...
}

Parameters

We will create two streams with same stream parameters required by the create function.

address sender = msg.sender;
address firstRecipient = address(0xCAFE);
address secondRecipient = address(0xBEEF);
UD21x18 firstRatePerSecond = ud21x18(0.0001e18);
UD21x18 secondRatePerSecond = ud21x18(0.0002e18);
bool transferable = true;

Construct an array of bytes of length 2 to be passed into the batch function:

bytes[] memory calls = new bytes[](2);
calls[0] = abi.encodeCall(FLOW.create, (sender, firstRecipient, firstRatePerSecond, USDC, transferable));
calls[1] = abi.encodeCall(FLOW.create, (sender, secondRecipient, secondRatePerSecond, USDC, transferable));

Since we are creating two streams, the function will return an array containing the two generated stream IDs:

uint256 nextStreamId = FLOW.nextStreamId();
streamIds = new uint256[](2);
streamIds[0] = nextStreamId;
streamIds[1] = nextStreamId + 1;

Execute the batch:

FLOW.batch(calls);

Homework

Try to implement the following ideas using batch function:

  • Adjust Rate Per Second and Deposit
  • Pause and Withdraw Max
  • Void and Withdraw Max
  • Multiple Withdraw Max

Below, you will find the full code for it.

Other ideas

There are plenty of other possibilities as well! Feel free to experiment and come up with combinations that suit your system. 🚀

Full code

Below you can see the complete FlowBatchable contract:

Flow Batchable
loading...