Skip to content

Commit

Permalink
refactor: batch function (#358)
Browse files Browse the repository at this point in the history
* refactor: batch function

* test: add a payable test for batch
  • Loading branch information
smol-ninja authored Jan 6, 2025
1 parent b5df197 commit f06873d
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 186 deletions.
4 changes: 2 additions & 2 deletions remappings.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/
@prb/math/=node_modules/@prb/math/
forge-std/=node_modules/forge-std/
solady/=node_modules/solady/
forge-std/=node_modules/forge-std/
solady/=node_modules/solady/
21 changes: 17 additions & 4 deletions src/abstracts/Batch.sol
Original file line number Diff line number Diff line change
@@ -1,26 +1,39 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// solhint-disable no-inline-assembly
pragma solidity >=0.8.22;

import { IBatch } from "../interfaces/IBatch.sol";
import { Errors } from "../libraries/Errors.sol";

/// @title Batch
/// @notice See the documentation in {IBatch}.
/// @dev Forked from: https://github.com/boringcrypto/BoringSolidity/blob/master/contracts/BoringBatchable.sol
abstract contract Batch is IBatch {
/*//////////////////////////////////////////////////////////////////////////
USER-FACING NON-CONSTANT FUNCTIONS
//////////////////////////////////////////////////////////////////////////*/

/// @inheritdoc IBatch
function batch(bytes[] calldata calls) external payable override {
/// @dev Since `msg.value` can be reused across calls, be VERY CAREFUL when using it. Refer to
/// https://paradigm.xyz/2021/08/two-rights-might-make-a-wrong for more information.
function batch(bytes[] calldata calls) external payable override returns (bytes[] memory results) {
uint256 count = calls.length;
results = new bytes[](count);

for (uint256 i = 0; i < count; ++i) {
(bool success, bytes memory result) = address(this).delegatecall(calls[i]);

// Check: If the delegatecall failed, load and bubble up the revert data.
if (!success) {
revert Errors.BatchError(result);
assembly {
// Get the length of the result stored in the first 32 bytes.
let resultSize := mload(result)

// Forward the pointer by 32 bytes to skip the length argument, and revert with the result.
revert(add(32, result), resultSize)
}
}

// Push the result into the results array.
results[i] = result;
}
}
}
7 changes: 5 additions & 2 deletions src/interfaces/IBatch.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ pragma solidity >=0.8.22;

/// @notice This contract implements logic to batch call any function.
interface IBatch {
/// @notice Allows batched call to self, `this` contract.
/// @notice Allows batched calls to self, i.e., `this` contract.
/// @dev Since `msg.value` can be reused across calls, be VERY CAREFUL when using it. Refer to
/// https://paradigm.xyz/2021/08/two-rights-might-make-a-wrong for more information.
/// @param calls An array of inputs for each call.
function batch(bytes[] calldata calls) external payable;
/// @return results An array of results from each call. Empty when the calls do not return anything.
function batch(bytes[] calldata calls) external payable returns (bytes[] memory results);
}
1 change: 0 additions & 1 deletion tests/fork/Fork.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ pragma solidity >=0.8.22;

import { IERC20Metadata } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { ISablierFlow } from "src/interfaces/ISablierFlow.sol";
import { SablierFlow } from "src/SablierFlow.sol";

import { Base_Test } from "../Base.t.sol";
Expand Down
Loading

0 comments on commit f06873d

Please sign in to comment.