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");
}
}
Submitted on: 2025-09-17 13:06:27
Comments
Log in to comment.
No comments yet.