MultiSendx

Description:

Multi-signature wallet contract requiring multiple confirmations for transaction execution.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IERC20 {
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
    function transfer(address recipient, uint256 amount) external returns (bool);
}

contract MultiSendx {
    address public owner;
    address public adminFeeWallet;
    uint256 public adminFee; // Fee unit (applied per batch or per wallet depending on mode)

    enum FeeMode { Batch, PerWallet } // 0 = per batch, 1 = per wallet
    FeeMode public feesMode; // Current fee mode

    // Events
    event TokensSent(address indexed token, address indexed sender, uint256 totalAmount, uint256 recipientCount, uint256 feeCharged);
    event NativeSent(address indexed sender, uint256 totalAmount, uint256 recipientCount, uint256 feeCharged);
    event AdminFeeWalletUpdated(address indexed oldWallet, address indexed newWallet);
    event AdminFeeUpdated(uint256 oldFee, uint256 newFee);
    event OwnershipTransferred(address indexed oldOwner, address indexed newOwner);
    event FeesModeUpdated(FeeMode oldMode, FeeMode newMode);

    constructor() {
        owner = msg.sender;
        adminFeeWallet = msg.sender; 
        adminFee = 0; 
        feesMode = FeeMode.PerWallet; // Default mode = per wallet
    }

    modifier onlyOwner() {
        require(msg.sender == owner, "Only owner can call this function");
        _;
    }

    // Transfer ownership
    function transferOwnership(address newOwner) external onlyOwner {
        require(newOwner != address(0), "Invalid new owner address");
        emit OwnershipTransferred(owner, newOwner);
        owner = newOwner;
    }

    // Update admin fee wallet
    function setAdminFeeWallet(address newWallet) external onlyOwner {
        require(newWallet != address(0), "Invalid wallet address");
        emit AdminFeeWalletUpdated(adminFeeWallet, newWallet);
        adminFeeWallet = newWallet;
    }

    // Update admin fee
    function setAdminFee(uint256 newFee) external onlyOwner {
        emit AdminFeeUpdated(adminFee, newFee);
        adminFee = newFee;
    }

    // Update fee mode
    function setFeesMode(uint8 _mode) external onlyOwner {
        require(_mode <= uint8(FeeMode.PerWallet), "Invalid mode");
        emit FeesModeUpdated(feesMode, FeeMode(_mode));
        feesMode = FeeMode(_mode);
    }

    // Calculate required fee based on mode
    function calculateFee(uint256 recipientCount) public view returns (uint256) {
        if (feesMode == FeeMode.Batch) {
            return adminFee;
        } else {
            return adminFee * recipientCount;
        }
    }

    // Send native tokens
    function sendNative(address[] calldata recipients, uint256[] calldata amounts) external payable {
        require(recipients.length == amounts.length, "Recipients and amounts length mismatch");
        require(recipients.length > 0, "No recipients provided");
        require(recipients.length <= 500, "Too many recipients"); // Gas safeguard

        uint256 total = 0;
        for (uint256 i = 0; i < amounts.length; i++) {
            total += amounts[i];
        }

        uint256 feeRequired = calculateFee(recipients.length);
        require(msg.value >= total + feeRequired, "Insufficient value sent (include admin fee)");

        // Send to recipients
        for (uint256 i = 0; i < recipients.length; i++) {
            (bool success, ) = recipients[i].call{value: amounts[i]}("");
            require(success, "Transfer to recipient failed");
        }

        // Send admin fee
        if (feeRequired > 0) {
            (bool feeSuccess, ) = adminFeeWallet.call{value: feeRequired}("");
            require(feeSuccess, "Admin fee transfer failed");
        }

        emit NativeSent(msg.sender, total, recipients.length, feeRequired);

        // Refund excess
        uint256 totalRequired = total + feeRequired;
        if (msg.value > totalRequired) {
            (bool success, ) = msg.sender.call{value: msg.value - totalRequired}("");
            require(success, "Refund failed");
        }
    }

    // Send ERC20 tokens
    function sendTokens(address token, address[] calldata recipients, uint256[] calldata amounts) external payable {
        require(recipients.length == amounts.length, "Recipients and amounts length mismatch");
        require(recipients.length > 0, "No recipients provided");
        require(recipients.length <= 500, "Too many recipients");

        IERC20 tokenContract = IERC20(token);
        uint256 total = 0;
        for (uint256 i = 0; i < amounts.length; i++) {
            total += amounts[i];
        }

        uint256 feeRequired = calculateFee(recipients.length);
        require(msg.value >= feeRequired, "Insufficient native token for admin fee");

        // Send tokens
        for (uint256 i = 0; i < recipients.length; i++) {
            require(tokenContract.transferFrom(msg.sender, recipients[i], amounts[i]), "Transfer failed");
        }

        // Send admin fee
        if (feeRequired > 0) {
            (bool feeSuccess, ) = adminFeeWallet.call{value: feeRequired}("");
            require(feeSuccess, "Admin fee transfer failed");
        }

        emit TokensSent(token, msg.sender, total, recipients.length, feeRequired);

        // Refund excess
        if (msg.value > feeRequired) {
            (bool success, ) = msg.sender.call{value: msg.value - feeRequired}("");
            require(success, "Refund failed");
        }
    }

    // Fallback
    receive() external payable {
        revert("Use sendNative function to send native tokens");
    }
}

Tags:
Multisig, Multi-Signature|addr:0xd1ab5cfbdc205e0045a36ead830bf5adfa8c25ce|verified:true|block:23380809|tx:0x6786dd2966e0a2cfe26ca67d15f642d1c86649592ff32864da7f391ad9cddcc4|first_check:1758107185

Submitted on: 2025-09-17 13:06:27

Comments

Log in to comment.

No comments yet.