BatchTransfer

Description:

Smart contract deployed on Ethereum with Factory features.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "src/BatchTransfer.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

/**
 * @title BatchTransfer
 * @notice Contract for efficient batch ETH transfers
 * @dev Saves ~45% gas for 5 wallets compared to individual transfers
 */
contract BatchTransfer {
    address public immutable owner;

    event BatchTransferExecuted(uint256 recipientCount, uint256 amountEach, uint256 totalAmount);
    event EmergencyWithdrawal(address indexed owner, uint256 amount);

    error Unauthorized();
    error InvalidInput();
    error TransferFailed(address recipient);
    error InsufficientValue();

    modifier onlyOwner() {
        if (msg.sender != owner) revert Unauthorized();
        _;
    }

    constructor(address _owner) {
        require(_owner != address(0), "Owner address cannot be zero");
        owner = _owner;
    }

    /**
     * @notice Transfer same amount of ETH to multiple addresses
     * @param recipients Array of recipient addresses
     * @param amountEach Amount of ETH to send to each recipient (in wei)
     */
    function batchTransferSame(address payable[] calldata recipients, uint256 amountEach) external payable onlyOwner {
        uint256 recipientCount = recipients.length;

        if (recipientCount == 0) revert InvalidInput();
        if (amountEach == 0) revert InvalidInput();

        uint256 totalRequired = recipientCount * amountEach;
        if (msg.value < totalRequired) revert InsufficientValue();

        for (uint256 i = 0; i < recipientCount;) {
            (bool success,) = recipients[i].call{value: amountEach}("");
            if (!success) revert TransferFailed(recipients[i]);

            unchecked {
                ++i;
            }
        }

        emit BatchTransferExecuted(recipientCount, amountEach, totalRequired);

        // Refund excess ETH
        uint256 excess = msg.value - totalRequired;
        if (excess > 0) {
            (bool refundSuccess,) = payable(owner).call{value: excess}("");
            if (!refundSuccess) revert TransferFailed(owner);
        }
    }

    /**
     * @notice Transfer different amounts of ETH to multiple addresses
     * @param recipients Array of recipient addresses
     * @param amounts Array of amounts to send (must match recipients length)
     */
    function batchTransferDifferent(address payable[] calldata recipients, uint256[] calldata amounts)
        external
        payable
        onlyOwner
    {
        uint256 recipientCount = recipients.length;

        if (recipientCount == 0) revert InvalidInput();
        if (recipientCount != amounts.length) revert InvalidInput();

        uint256 totalRequired = 0;
        for (uint256 i = 0; i < recipientCount;) {
            totalRequired += amounts[i];
            unchecked {
                ++i;
            }
        }

        if (msg.value < totalRequired) revert InsufficientValue();

        for (uint256 i = 0; i < recipientCount;) {
            if (amounts[i] > 0) {
                (bool success,) = recipients[i].call{value: amounts[i]}("");
                if (!success) revert TransferFailed(recipients[i]);
            }

            unchecked {
                ++i;
            }
        }

        emit BatchTransferExecuted(recipientCount, 0, totalRequired);

        // Refund excess ETH
        uint256 excess = msg.value - totalRequired;
        if (excess > 0) {
            (bool refundSuccess,) = payable(owner).call{value: excess}("");
            if (!refundSuccess) revert TransferFailed(owner);
        }
    }

    /**
     * @notice Emergency withdraw all ETH from contract
     */
    function emergencyWithdraw() external onlyOwner {
        uint256 balance = address(this).balance;
        (bool success,) = payable(owner).call{value: balance}("");
        if (!success) revert TransferFailed(owner);

        emit EmergencyWithdrawal(owner, balance);
    }

    /**
     * @notice Allow contract to receive ETH
     */
    receive() external payable {}
}
"
    }
  },
  "settings": {
    "remappings": [
      "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
      "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
      "@gnosis.pm/safe-contracts/=lib/safe-contracts/",
      "@gnosis.pm/zodiac/=lib/zodiac/",
      "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
      "forge-std/=lib/forge-std/src/",
      "halmos-cheatcodes/=lib/openzeppelin-contracts-upgradeable/lib/halmos-cheatcodes/src/",
      "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
      "openzeppelin-contracts/=lib/openzeppelin-contracts/",
      "safe-contracts/=lib/safe-contracts/",
      "zodiac/=lib/zodiac/contracts/"
    ],
    "optimizer": {
      "enabled": false,
      "runs": 200
    },
    "metadata": {
      "useLiteralContent": false,
      "bytecodeHash": "ipfs",
      "appendCBOR": true
    },
    "outputSelection": {
      "*": {
        "*": [
          "evm.bytecode",
          "evm.deployedBytecode",
          "devdoc",
          "userdoc",
          "metadata",
          "abi"
        ]
      }
    },
    "evmVersion": "cancun",
    "viaIR": false
  }
}}

Tags:
Factory|addr:0xb36079c541a69a43ccd44d421db8a6d34cf7aff6|verified:true|block:23726490|tx:0x0d613a70029551e156e6dbdd6f88fc0855476153168873d5350c693c1b7e24bf|first_check:1762269377

Submitted on: 2025-11-04 16:16:19

Comments

Log in to comment.

No comments yet.