ETH Price: $1,981.81 (+0.20%)

Contract Diff Checker

Contract Name:
BatchDeposit2

Contract Source Code:

<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>

// SPDX-License-Identifier: GPL-3.0-or-later

// Contract: BatchDeposit2
// Repository: https://gitlab.com/Blockdaemon/open-source/eth2-batch-deposit-contract

pragma solidity 0.8.28;

import {IBatchDeposit2} from "./interfaces/IBatchDeposit2.sol";
import {IERC165} from "./interfaces/IERC165.sol";

contract BatchDeposit2 is IBatchDeposit2, IERC165 {
    // 0xd0 == 0x30 + 0x20 + 0x60 + 0x20 (pubkey + credentials + signature + root)
    uint256 public constant DEPOSIT_DATA_SIZE = 0xd0;

    address public immutable DEPOSIT_CONTRACT;

    error DeadlineExceeded();
    error DepositFailed();
    error ExcessiveBalance();
    error FundingNotAccepted();
    error InvalidLength();
    error ZeroAddress();

    constructor(address depositContract) {
        require(depositContract != address(0), ZeroAddress());
        DEPOSIT_CONTRACT = depositContract;
    }

    receive() external payable override {
        revert FundingNotAccepted();
    }

    fallback() external payable override {
        revert FundingNotAccepted();
    }

    function batchDeposit(uint256 deadline, uint256[] calldata values, bytes calldata argv) external payable override {
        require(block.number <= deadline, DeadlineExceeded());
        require(argv.length == values.length * DEPOSIT_DATA_SIZE, InvalidLength());

        uint256 balanceBefore = address(this).balance;

        address depositContract = DEPOSIT_CONTRACT;
        assembly {
            // copy selector
            mstore(0x0080, 0x2289511800000000000000000000000000000000000000000000000000000000)
            // copy pubkey offset
            mstore(0x0084, 0x0000000000000000000000000000000000000000000000000000000000000080)
            // copy withdrawal_credentials offset
            mstore(0x00a4, 0x00000000000000000000000000000000000000000000000000000000000000e0)
            // copy signature offset
            mstore(0x00c4, 0x0000000000000000000000000000000000000000000000000000000000000120)
            // copy pubkey length
            mstore(0x0104, 0x0000000000000000000000000000000000000000000000000000000000000030)
            // copy withdrawal_credentials length
            mstore(0x0164, 0x0000000000000000000000000000000000000000000000000000000000000020)
            // copy signature length
            mstore(0x01a4, 0x0000000000000000000000000000000000000000000000000000000000000060)

            let argvOffset := argv.offset
            let valuesOffset := values.offset

            for { let i := 0 } lt(i, values.length) { i := add(i, 1) } {
                // copy pubkey
                calldatacopy(0x0124, add(argvOffset, 0), 0x30)

                // copy withdrawal credentials
                calldatacopy(0x0184, add(argvOffset, 0x30), 0x20)

                // copy signature
                calldatacopy(0x01c4, add(argvOffset, 0x50), 0x60)

                // copy deposit_data_root
                calldatacopy(0x0e4, add(argvOffset, 0xb0), 0x20)

                if iszero(call(gas(), depositContract, calldataload(valuesOffset), 0x80, 0x1a4, 0, 0)) {
                    // DepositFailed()
                    mstore(0x00, 0x79cacff100000000000000000000000000000000000000000000000000000000)
                    revert(0x00, 0x04)
                }

                // adjust offsets
                argvOffset := add(argvOffset, 0xd0)
                valuesOffset := add(valuesOffset, 0x20)
            }
        }

        uint256 balanceAfter = address(this).balance;
        require(balanceBefore == balanceAfter + msg.value, ExcessiveBalance());
    }

    function supportsInterface(bytes4 interfaceId) external pure override returns (bool) {
        return interfaceId == type(IERC165).interfaceId || interfaceId == type(IBatchDeposit2).interfaceId;
    }
}

<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>

// SPDX-License-Identifier: GPL-3.0-or-later

pragma solidity 0.8.28;

interface IBatchDeposit2 {
    receive() external payable;

    fallback() external payable;

    function batchDeposit(uint256 deadline, uint256[] calldata values, bytes calldata args) external payable;
}

<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>

// SPDX-License-Identifier: GPL-3.0-or-later

pragma solidity 0.8.28;

interface IERC165 {
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

Please enter a contract address above to load the contract details and source code.

Context size (optional):