SimpleWallet

Description:

Smart contract deployed on Ethereum.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

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

interface IERC20 {
    function balanceOf(address account) external view returns (uint256);
}

contract SimpleWallet {
    address public owner;

    event Received(address indexed sender, uint256 amount);
    event Sent(address indexed to, uint256 amount);
    event OwnerChanged(address indexed oldOwner, address indexed newOwner);
    event ERC20Sent(address indexed token, address indexed to, uint256 amount);
    event ERC20Recovered(address indexed token, address indexed to, uint256 amount);

    modifier onlyOwner() {
        require(msg.sender == owner, "not owner");
        _;
    }

    bool private locked;
    modifier noReentrant() {
        require(!locked, "reentrant");
        locked = true;
        _;
        locked = false;
    }

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

    receive() external payable {
        emit Received(msg.sender, msg.value);
    }

    fallback() external payable {
        emit Received(msg.sender, msg.value);
    }

    function balance() external view returns (uint256) {
        return address(this).balance;
    }

    function changeOwner(address newOwner) external onlyOwner {
        require(newOwner != address(0), "zero new owner");
        emit OwnerChanged(owner, newOwner);
        owner = newOwner;
    }

    function sendEther(address payable to, uint256 amount) external onlyOwner noReentrant returns (bool) {
        require(to != address(0), "zero to");
        require(address(this).balance >= amount, "insufficient balance");
        (bool ok, ) = to.call{value: amount}("");
        require(ok, "send failed");
        emit Sent(to, amount);
        return ok;
    }

    /// -----------------
    /// ✅ 批量 ETH 转账
    /// -----------------
    function batchSendEther(address payable[] calldata to, uint256[] calldata amounts) 
        external onlyOwner noReentrant returns (bool) 
    {
        require(to.length == amounts.length, "array length mismatch");
        for (uint256 i = 0; i < to.length; i++) {
            require(to[i] != address(0), "zero to");
            require(address(this).balance >= amounts[i], "insufficient balance");
            (bool ok, ) = to[i].call{value: amounts[i]}("");
            require(ok, "send failed");
            emit Sent(to[i], amounts[i]);
        }
        return true;
    }

    function withdrawAll() external onlyOwner noReentrant returns (bool) {
        uint256 bal = address(this).balance;
        require(bal > 0, "no balance");
        (bool ok, ) = payable(owner).call{value: bal}("");
        require(ok, "withdraw failed");
        emit Sent(owner, bal);
        return ok;
    }

    function sendERC20(address token, address to, uint256 amount) external onlyOwner noReentrant returns (bool) {
        require(token != address(0), "zero token");
        require(to != address(0), "zero to");
        require(amount > 0, "zero amount");
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, amount));
        require(success && (data.length == 0 || abi.decode(data, (bool))), "ERC20: transfer failed");
        emit ERC20Sent(token, to, amount);
        return true;
    }

    /// -----------------
    /// ✅ 批量 ERC20 转账
    /// -----------------
    function batchSendERC20(address token, address[] calldata to, uint256[] calldata amounts) 
        external onlyOwner noReentrant returns (bool) 
    {
        require(token != address(0), "zero token");
        require(to.length == amounts.length, "array length mismatch");

        for (uint256 i = 0; i < to.length; i++) {
            require(to[i] != address(0), "zero to");
            require(amounts[i] > 0, "zero amount");
            (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to[i], amounts[i]));
            require(success && (data.length == 0 || abi.decode(data, (bool))), "ERC20: transfer failed");
            emit ERC20Sent(token, to[i], amounts[i]);
        }
        return true;
    }

    function recoverERC20(address token) external onlyOwner noReentrant returns (bool) {
        require(token != address(0), "zero token");
        uint256 bal = IERC20(token).balanceOf(address(this));
        require(bal > 0, "no token balance");
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, owner, bal));
        require(success && (data.length == 0 || abi.decode(data, (bool))), "ERC20: recover failed");
        emit ERC20Recovered(token, owner, bal);
        return true;
    }

    function tokenBalance(address token) external view returns (uint256) {
        if (token == address(0)) return 0;
        return IERC20(token).balanceOf(address(this));
    }
}

Tags:
addr:0x49e7a9d81139fc95ebc81ab58b2c5f8d4c1f7115|verified:true|block:23439833|tx:0x07a6df3073c0fd0e071819bc2e8908aa9d1541ebc359fb163d1df73e099d2b6d|first_check:1758801024

Submitted on: 2025-09-25 13:50:25

Comments

Log in to comment.

No comments yet.