Transaction Hash:
Block:
17196626 at May-05-2023 07:51:35 PM +UTC
Transaction Fee:
0.008060365976781522 ETH
$18.12
Gas Used:
50,514 Gas / 159.566971073 Gwei
Emitted Events:
277 |
DepositContract.DepositEvent( pubkey=0xA17DAB072DA9A5D98978B9449352BDDF48D71C5E6D2A745F1AB2B0AE3D43C3E6F20773D143CBDD123BDAE02B21A59048, withdrawal_credentials=0x0100000000000000000000000513647E69D5B2ACCE36ACC31A8895989CD5178A, amount=0x0040597307000000, signature=0xA5C40B7550F52C2EA3FD20EB6F8C86AE0FF45BB067EB61B356B63A62EF2BB6138DB942F52D78931E6650871B96764D040C806FC5615B8FFBA8C6FA3800CE39DB479D6E0D2C987C87C255D157DF68EA87E3658A10967B198C1975588A75BBE4A1, index=0x3AF2090000000000 )
|
Account State Difference:
Address | Before | After | State Difference | ||
---|---|---|---|---|---|
0x00000000...03d7705Fa | (Beacon Deposit Contract) | 20,217,449.194325012575404192 Eth | 20,217,481.194325012575404192 Eth | 32 | |
0x0513647e...89cD5178A |
172.69344681690659125 Eth
Nonce: 207
|
140.685386450929809728 Eth
Nonce: 208
| 32.008060365976781522 | ||
0x6b3A8798...6694e55d0
Miner
| (Fee Recipient: 0x6b3a...5d0) | 15.087208797145172091 Eth | 15.087213848545172091 Eth | 0.0000050514 |
Execution Trace
ETH 32
DepositContract.deposit( pubkey=0xA17DAB072DA9A5D98978B9449352BDDF48D71C5E6D2A745F1AB2B0AE3D43C3E6F20773D143CBDD123BDAE02B21A59048, withdrawal_credentials=0x0100000000000000000000000513647E69D5B2ACCE36ACC31A8895989CD5178A, signature=0xA5C40B7550F52C2EA3FD20EB6F8C86AE0FF45BB067EB61B356B63A62EF2BB6138DB942F52D78931E6650871B96764D040C806FC5615B8FFBA8C6FA3800CE39DB479D6E0D2C987C87C255D157DF68EA87E3658A10967B198C1975588A75BBE4A1, deposit_data_root=837868B164A6386BE23F4DA1F5752F73F3C41FB1E60444759B879B48D8AB7EDA )
-
Null: 0x000...002.a17dab07( )
-
Null: 0x000...002.a5c40b75( )
-
Null: 0x000...002.479d6e0d( )
-
Null: 0x000...002.434a85f0( )
-
Null: 0x000...002.3d005a09( )
-
Null: 0x000...002.00405973( )
-
Null: 0x000...002.a754e769( )
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]; } }