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));
}
}
}
Submitted on: 2025-09-30 11:23:30
Comments
Log in to comment.
No comments yet.