DepositIndexDecoder

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;

/**
 * @title DepositIndexDecoder
 * @notice Utility to convert the Ethereum DepositContract's little-endian 8-byte `index` (emitted as `bytes`)
 *         into a normal big-endian decimal `uint64`. The DepositEvent shape is:
 *         event DepositEvent(bytes pubkey, bytes withdrawal_credentials, bytes amount, bytes signature, bytes index);
 *
 *         Per the canonical DepositContract, `index` is the deposit_count encoded as a little-endian 64-bit number.
 *         See: https://github.com/ethereum/consensus-specs (Phase0) and the DepositContract implementation.
 *
 * @dev This contract is deliberately tiny, pure, and gas-efficient. It accepts either `bytes` or `bytes8`.
 */
contract DepositIndexDecoder {
    error InvalidIndexLength(uint256 provided);

    /**
     * @notice Decode the deposit `index` (little-endian 8-byte) to uint64.
     * @param indexLE The raw `bytes` exactly length 8 from the DepositEvent's `index` field.
     * @return index The decoded unsigned 64-bit integer in normal (big-endian) numeric form.
     */
    function decodeIndex(bytes calldata indexLE) external pure returns (uint64 index) {
        if (indexLE.length != 8) revert InvalidIndexLength(indexLE.length);
        // Little-endian to uint64: index = sum(indexLE[i] << (8*i)) for i in [0..7]
        unchecked {
            index = uint64(uint8(indexLE[0]))
                | (uint64(uint8(indexLE[1])) << 8)
                | (uint64(uint8(indexLE[2])) << 16)
                | (uint64(uint8(indexLE[3])) << 24)
                | (uint64(uint8(indexLE[4])) << 32)
                | (uint64(uint8(indexLE[5])) << 40)
                | (uint64(uint8(indexLE[6])) << 48)
                | (uint64(uint8(indexLE[7])) << 56);
        }
    }

    /**
     * @notice Same as {decodeIndex} but accepts a fixed-size `bytes8`.
     */
    function decodeIndex(bytes8 indexLE) external pure returns (uint64 index) {
        // Inline expand for gas; solidity shifts on bytesN require casting.
        unchecked {
            index = uint64(uint8(indexLE[0]))
                | (uint64(uint8(indexLE[1])) << 8)
                | (uint64(uint8(indexLE[2])) << 16)
                | (uint64(uint8(indexLE[3])) << 24)
                | (uint64(uint8(indexLE[4])) << 32)
                | (uint64(uint8(indexLE[5])) << 40)
                | (uint64(uint8(indexLE[6])) << 48)
                | (uint64(uint8(indexLE[7])) << 56);
        }
    }

    /**
     * @notice Convenience: decode the `amount` field from the same DepositEvent (also little-endian 8-byte gwei amount).
     * @dev The DepositContract emits `amount` as little-endian 64-bit gwei. Useful if you need it on-chain alongside index.
     */
    function decodeAmount(bytes calldata amountLE) external pure returns (uint64 amountGwei) {
        if (amountLE.length != 8) revert InvalidIndexLength(amountLE.length);
        unchecked {
            amountGwei = uint64(uint8(amountLE[0]))
                | (uint64(uint8(amountLE[1])) << 8)
                | (uint64(uint8(amountLE[2])) << 16)
                | (uint64(uint8(amountLE[3])) << 24)
                | (uint64(uint8(amountLE[4])) << 32)
                | (uint64(uint8(amountLE[5])) << 40)
                | (uint64(uint8(amountLE[6])) << 48)
                | (uint64(uint8(amountLE[7])) << 56);
        }
    }

    /**
     * @notice Pure helper to round-trip encode a uint64 to little-endian 8-byte `bytes`.
     * @dev Handy for tests.
     */
    function encodeUint64LE(uint64 value) external pure returns (bytes memory out) {
        out = new bytes(8);
        unchecked {
            out[0] = bytes1(uint8(value));
            out[1] = bytes1(uint8(value >> 8));
            out[2] = bytes1(uint8(value >> 16));
            out[3] = bytes1(uint8(value >> 24));
            out[4] = bytes1(uint8(value >> 32));
            out[5] = bytes1(uint8(value >> 40));
            out[6] = bytes1(uint8(value >> 48));
            out[7] = bytes1(uint8(value >> 56));
        }
    }
}

Tags:
addr:0x99f8ab52d3318d6fc334eab3e4a2ea39edb03a94|verified:true|block:23473522|tx:0xdefd25dcd866103ecc32b9ca83fe696b331f671176b04fa199ef0fd5cc10ee8f|first_check:1759224210

Submitted on: 2025-09-30 11:23:30

Comments

Log in to comment.

No comments yet.