Transaction Hash:
Block:
23639304 at Oct-23-2025 09:27:11 AM +UTC
Transaction Fee:
0.000078145411913965 ETH
$0.15
Gas Used:
59,455 Gas / 1.314362323 Gwei
Emitted Events:
| 95 |
DepositContract.DepositEvent( pubkey=0xA8CEBB14F9D372BCB0C1237210A575A6C7544C4170B0EA75345380603EE5BB6C2EC9EAB3285FE930841C0E4289B5346E, withdrawal_credentials=0x0200000000000000000000009C4FA4EE466DFF080ADCCB12D39B99E83CDB1077, amount=0x00806E8774010000, signature=0xA68021A3EADC9F90AAB2AA0417BDF7E7A1108606A697A263FEACB88E9E6B80F5047FCEA4B7801C2A8D6E7FDB8B8753DB171542FA3FA2A522D187EAF3E904396F545E31F1CAFC0B9B1DA9843AA2D408BBDCB4CFAE54AC8657DD069E69B1F7433D, index=0x37F4220000000000 )
|
Account State Difference:
| Address | Before | After | State Difference | ||
|---|---|---|---|---|---|
| 0x00000000...03d7705Fa | (Beacon Deposit Contract) | 71,542,185.25245842769537452 Eth | 71,543,785.25245842769537452 Eth | 1,600 | |
| 0x9C4fA4Ee...83cdb1077 | (GMO Coin 1) |
3,433.646142779754940279 Eth
Nonce: 4752
|
1,833.646064634343026314 Eth
Nonce: 4753
| 1,600.000078145411913965 | |
|
0xdadB0d80...24f783711
Miner
| (BuilderNet) | 28.154064079071068143 Eth | 28.154135425071068143 Eth | 0.000071346 |
Execution Trace
ETH 1600
DepositContract.deposit( pubkey=0xA8CEBB14F9D372BCB0C1237210A575A6C7544C4170B0EA75345380603EE5BB6C2EC9EAB3285FE930841C0E4289B5346E, withdrawal_credentials=0x0200000000000000000000009C4FA4EE466DFF080ADCCB12D39B99E83CDB1077, signature=0xA68021A3EADC9F90AAB2AA0417BDF7E7A1108606A697A263FEACB88E9E6B80F5047FCEA4B7801C2A8D6E7FDB8B8753DB171542FA3FA2A522D187EAF3E904396F545E31F1CAFC0B9B1DA9843AA2D408BBDCB4CFAE54AC8657DD069E69B1F7433D, deposit_data_root=3339BAB575F5F89BC1C47A3A4394631F3FD877D3244B152ACE5FFD64B30652D0 )
-
Null: 0x000...002.a8cebb14( )
-
Null: 0x000...002.a68021a3( )
-
Null: 0x000...002.545e31f1( )
-
Null: 0x000...002.b2b6fee0( )
-
Null: 0x000...002.b7e0eaea( )
-
Null: 0x000...002.00806e87( )
-
Null: 0x000...002.cf9d6e0d( )
-
Null: 0x000...002.7ae2aa40( )
-
Null: 0x000...002.7e6fa9a6( )
-
Null: 0x000...002.36a1c2f0( )
deposit[DepositContract (ln:101)]
type[DepositContract (ln:116)]to_little_endian_64[DepositContract (ln:119)]DepositEvent[DepositContract (ln:120)]to_little_endian_64[DepositContract (ln:125)]sha256[DepositContract (ln:129)]sha256[DepositContract (ln:130)]sha256[DepositContract (ln:131)]sha256[DepositContract (ln:132)]sha256[DepositContract (ln:134)]sha256[DepositContract (ln:135)]sha256[DepositContract (ln:136)]sha256[DepositContract (ln:153)]
// ┏━━━┓━┏┓━┏┓━━┏━━━┓━━┏━━━┓━━━━┏━━━┓━━━━━━━━━━━━━━━━━━━┏┓━━━━━┏━━━┓━━━━━━━━━┏┓━━━━━━━━━━━━━━┏┓━
// ┃┏━━┛┏┛┗┓┃┃━━┃┏━┓┃━━┃┏━┓┃━━━━┗┓┏┓┃━━━━━━━━━━━━━━━━━━┏┛┗┓━━━━┃┏━┓┃━━━━━━━━┏┛┗┓━━━━━━━━━━━━┏┛┗┓
// ┃┗━━┓┗┓┏┛┃┗━┓┗┛┏┛┃━━┃┃━┃┃━━━━━┃┃┃┃┏━━┓┏━━┓┏━━┓┏━━┓┏┓┗┓┏┛━━━━┃┃━┗┛┏━━┓┏━┓━┗┓┏┛┏━┓┏━━┓━┏━━┓┗┓┏┛
// ┃┏━━┛━┃┃━┃┏┓┃┏━┛┏┛━━┃┃━┃┃━━━━━┃┃┃┃┃┏┓┃┃┏┓┃┃┏┓┃┃━━┫┣┫━┃┃━━━━━┃┃━┏┓┃┏┓┃┃┏┓┓━┃┃━┃┏┛┗━┓┃━┃┏━┛━┃┃━
// ┃┗━━┓━┃┗┓┃┃┃┃┃┃┗━┓┏┓┃┗━┛┃━━━━┏┛┗┛┃┃┃━┫┃┗┛┃┃┗┛┃┣━━┃┃┃━┃┗┓━━━━┃┗━┛┃┃┗┛┃┃┃┃┃━┃┗┓┃┃━┃┗┛┗┓┃┗━┓━┃┗┓
// ┗━━━┛━┗━┛┗┛┗┛┗━━━┛┗┛┗━━━┛━━━━┗━━━┛┗━━┛┃┏━┛┗━━┛┗━━┛┗┛━┗━┛━━━━┗━━━┛┗━━┛┗┛┗┛━┗━┛┗┛━┗━━━┛┗━━┛━┗━┛
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┃┃━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┗┛━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// SPDX-License-Identifier: CC0-1.0
pragma solidity 0.6.11;
// This interface is designed to be compatible with the Vyper version.
/// @notice This is the Ethereum 2.0 deposit contract interface.
/// For more information see the Phase 0 specification under https://github.com/ethereum/eth2.0-specs
interface IDepositContract {
/// @notice A processed deposit event.
event DepositEvent(
bytes pubkey,
bytes withdrawal_credentials,
bytes amount,
bytes signature,
bytes index
);
/// @notice Submit a Phase 0 DepositData object.
/// @param pubkey A BLS12-381 public key.
/// @param withdrawal_credentials Commitment to a public key for withdrawals.
/// @param signature A BLS12-381 signature.
/// @param deposit_data_root The SHA-256 hash of the SSZ-encoded DepositData object.
/// Used as a protection against malformed input.
function deposit(
bytes calldata pubkey,
bytes calldata withdrawal_credentials,
bytes calldata signature,
bytes32 deposit_data_root
) external payable;
/// @notice Query the current deposit root hash.
/// @return The deposit root hash.
function get_deposit_root() external view returns (bytes32);
/// @notice Query the current deposit count.
/// @return The deposit count encoded as a little endian 64-bit number.
function get_deposit_count() external view returns (bytes memory);
}
// Based on official specification in https://eips.ethereum.org/EIPS/eip-165
interface ERC165 {
/// @notice Query if a contract implements an interface
/// @param interfaceId The interface identifier, as specified in ERC-165
/// @dev Interface identification is specified in ERC-165. This function
/// uses less than 30,000 gas.
/// @return `true` if the contract implements `interfaceId` and
/// `interfaceId` is not 0xffffffff, `false` otherwise
function supportsInterface(bytes4 interfaceId) external pure returns (bool);
}
// This is a rewrite of the Vyper Eth2.0 deposit contract in Solidity.
// It tries to stay as close as possible to the original source code.
/// @notice This is the Ethereum 2.0 deposit contract interface.
/// For more information see the Phase 0 specification under https://github.com/ethereum/eth2.0-specs
contract DepositContract is IDepositContract, ERC165 {
uint constant DEPOSIT_CONTRACT_TREE_DEPTH = 32;
// NOTE: this also ensures `deposit_count` will fit into 64-bits
uint constant MAX_DEPOSIT_COUNT = 2**DEPOSIT_CONTRACT_TREE_DEPTH - 1;
bytes32[DEPOSIT_CONTRACT_TREE_DEPTH] branch;
uint256 deposit_count;
bytes32[DEPOSIT_CONTRACT_TREE_DEPTH] zero_hashes;
constructor() public {
// Compute hashes in empty sparse Merkle tree
for (uint height = 0; height < DEPOSIT_CONTRACT_TREE_DEPTH - 1; height++)
zero_hashes[height + 1] = sha256(abi.encodePacked(zero_hashes[height], zero_hashes[height]));
}
function get_deposit_root() override external view returns (bytes32) {
bytes32 node;
uint size = deposit_count;
for (uint height = 0; height < DEPOSIT_CONTRACT_TREE_DEPTH; height++) {
if ((size & 1) == 1)
node = sha256(abi.encodePacked(branch[height], node));
else
node = sha256(abi.encodePacked(node, zero_hashes[height]));
size /= 2;
}
return sha256(abi.encodePacked(
node,
to_little_endian_64(uint64(deposit_count)),
bytes24(0)
));
}
function get_deposit_count() override external view returns (bytes memory) {
return to_little_endian_64(uint64(deposit_count));
}
function deposit(
bytes calldata pubkey,
bytes calldata withdrawal_credentials,
bytes calldata signature,
bytes32 deposit_data_root
) override external payable {
// Extended ABI length checks since dynamic types are used.
require(pubkey.length == 48, "DepositContract: invalid pubkey length");
require(withdrawal_credentials.length == 32, "DepositContract: invalid withdrawal_credentials length");
require(signature.length == 96, "DepositContract: invalid signature length");
// Check deposit amount
require(msg.value >= 1 ether, "DepositContract: deposit value too low");
require(msg.value % 1 gwei == 0, "DepositContract: deposit value not multiple of gwei");
uint deposit_amount = msg.value / 1 gwei;
require(deposit_amount <= type(uint64).max, "DepositContract: deposit value too high");
// Emit `DepositEvent` log
bytes memory amount = to_little_endian_64(uint64(deposit_amount));
emit DepositEvent(
pubkey,
withdrawal_credentials,
amount,
signature,
to_little_endian_64(uint64(deposit_count))
);
// Compute deposit data root (`DepositData` hash tree root)
bytes32 pubkey_root = sha256(abi.encodePacked(pubkey, bytes16(0)));
bytes32 signature_root = sha256(abi.encodePacked(
sha256(abi.encodePacked(signature[:64])),
sha256(abi.encodePacked(signature[64:], bytes32(0)))
));
bytes32 node = sha256(abi.encodePacked(
sha256(abi.encodePacked(pubkey_root, withdrawal_credentials)),
sha256(abi.encodePacked(amount, bytes24(0), signature_root))
));
// Verify computed and expected deposit data roots match
require(node == deposit_data_root, "DepositContract: reconstructed DepositData does not match supplied deposit_data_root");
// Avoid overflowing the Merkle tree (and prevent edge case in computing `branch`)
require(deposit_count < MAX_DEPOSIT_COUNT, "DepositContract: merkle tree full");
// Add deposit data root to Merkle tree (update a single `branch` node)
deposit_count += 1;
uint size = deposit_count;
for (uint height = 0; height < DEPOSIT_CONTRACT_TREE_DEPTH; height++) {
if ((size & 1) == 1) {
branch[height] = node;
return;
}
node = sha256(abi.encodePacked(branch[height], node));
size /= 2;
}
// As the loop should always end prematurely with the `return` statement,
// this code should be unreachable. We assert `false` just to be safe.
assert(false);
}
function supportsInterface(bytes4 interfaceId) override external pure returns (bool) {
return interfaceId == type(ERC165).interfaceId || interfaceId == type(IDepositContract).interfaceId;
}
function to_little_endian_64(uint64 value) internal pure returns (bytes memory ret) {
ret = new bytes(8);
bytes8 bytesValue = bytes8(value);
// Byteswapping during copying to bytes.
ret[0] = bytesValue[7];
ret[1] = bytesValue[6];
ret[2] = bytesValue[5];
ret[3] = bytesValue[4];
ret[4] = bytesValue[3];
ret[5] = bytesValue[2];
ret[6] = bytesValue[1];
ret[7] = bytesValue[0];
}
}