ETH Price: $2,424.72 (-2.79%)
Gas: 0.52 Gwei

Transaction Decoder

Block:
17035779 at Apr-13-2023 02:02:47 AM +UTC
Transaction Fee:
0.001970557972128959 ETH $4.78
Gas Used:
73,613 Gas / 26.769157243 Gwei

Emitted Events:

169 DepositContract.DepositEvent( pubkey=0xAD1FE46AEE30697B3DCC81E129093370E33D329EC8E6B6D51BE757B8C1357BEE58E0147C7ADF31CE9E8719A501BC81E9, withdrawal_credentials=0x010000000000000000000000662F3F39FEDB7C57C2FA855E6BD234BE52595728, amount=0x0040597307000000, signature=0x9543FF9777529607ED590DF1D069AD018F081B97CCD846D1656B8047FBF0520A424C959B0A38BB75ED8D0D739BC415DB0AE597542772AA532E4CE47F8C2D64EF3FA3B20EF85D4A0BD2656734FF1770265AF047419D5EB1BE40147BD445221518, index=0x55E2080000000000 )
170 AbyssEth2Depositor.DepositEvent( from=[Sender] 0x662f3f39fedb7c57c2fa855e6bd234be52595728, nodesAmount=1 )

Account State Difference:

  Address   Before After State Difference Code
0x00000000...03d7705Fa
(Beacon Deposit Contract)
18,168,103.168232416675747075 Eth18,168,135.168232416675747075 Eth32
(Fee Recipient: 0x2990...088)
74.994237523907581434 Eth74.994342642184685489 Eth0.000105118277104055
0x662f3F39...E52595728
89.577552727122487558 Eth
Nonce: 117
57.575582169150358599 Eth
Nonce: 118
32.001970557972128959

Execution Trace

ETH 32 AbyssEth2Depositor.deposit( )
  • ETH 32 DepositContract.deposit( pubkey=0xAD1FE46AEE30697B3DCC81E129093370E33D329EC8E6B6D51BE757B8C1357BEE58E0147C7ADF31CE9E8719A501BC81E9, withdrawal_credentials=0x010000000000000000000000662F3F39FEDB7C57C2FA855E6BD234BE52595728, signature=0x9543FF9777529607ED590DF1D069AD018F081B97CCD846D1656B8047FBF0520A424C959B0A38BB75ED8D0D739BC415DB0AE597542772AA532E4CE47F8C2D64EF3FA3B20EF85D4A0BD2656734FF1770265AF047419D5EB1BE40147BD445221518, deposit_data_root=5C678593A5CAAE16940ACBAEAAA478E8900BCB8AA8A6745EEC9915272209847D )
    • Null: 0x000...002.ad1fe46a( )
    • Null: 0x000...002.9543ff97( )
    • Null: 0x000...002.3fa3b20e( )
    • Null: 0x000...002.2a92344a( )
    • Null: 0x000...002.bac7d56e( )
    • Null: 0x000...002.00405973( )
    • Null: 0x000...002.3ecc5e11( )
    • Null: 0x000...002.699ca201( )
      File 1 of 2: AbyssEth2Depositor
      /*
      ░█████╗░██████╗░██╗░░░██╗░██████╗░██████╗  ███████╗██╗███╗░░██╗░█████╗░███╗░░██╗░█████╗░███████╗
      ██╔══██╗██╔══██╗╚██╗░██╔╝██╔════╝██╔════╝  ██╔════╝██║████╗░██║██╔══██╗████╗░██║██╔══██╗██╔════╝
      ███████║██████╦╝░╚████╔╝░╚█████╗░╚█████╗░  █████╗░░██║██╔██╗██║███████║██╔██╗██║██║░░╚═╝█████╗░░
      ██╔══██║██╔══██╗░░╚██╔╝░░░╚═══██╗░╚═══██╗  ██╔══╝░░██║██║╚████║██╔══██║██║╚████║██║░░██╗██╔══╝░░
      ██║░░██║██████╦╝░░░██║░░░██████╔╝██████╔╝  ██║░░░░░██║██║░╚███║██║░░██║██║░╚███║╚█████╔╝███████╗
      ╚═╝░░╚═╝╚═════╝░░░░╚═╝░░░╚═════╝░╚═════╝░  ╚═╝░░░░░╚═╝╚═╝░░╚══╝╚═╝░░╚═╝╚═╝░░╚══╝░╚════╝░╚══════╝
      */
      // SPDX-License-Identifier: MIT
      pragma solidity ^0.8.0;
      import "@openzeppelin/contracts/access/Ownable.sol";
      import "@openzeppelin/contracts/utils/Pausable.sol";
      import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
      import "../contracts/interfaces/IDepositContract.sol";
      contract AbyssEth2Depositor is ReentrancyGuard, Pausable, Ownable {
          /**
           * @dev Eth2 Deposit Contract address.
           */
          IDepositContract public depositContract;
          /**
           * @dev Minimal and maximum amount of nodes per transaction.
           */
          uint256 public constant nodesMinAmount = 1;
          uint256 public constant nodesMaxAmount = 100;
          uint256 public constant pubkeyLength = 48;
          uint256 public constant credentialsLength = 32;
          uint256 public constant signatureLength = 96;
          /**
           * @dev Collateral size of one node.
           */
          uint256 public constant collateral = 32 ether;
          /**
           * @dev Setting Eth2 Smart Contract address during construction.
           */
          constructor(bool mainnet, address depositContract_) {
              if (mainnet == true) {
                  depositContract = IDepositContract(0x00000000219ab540356cBB839Cbe05303d7705Fa);
              } else if (depositContract_ == 0x0000000000000000000000000000000000000000) {
                  depositContract = IDepositContract(0x8c5fecdC472E27Bc447696F431E425D02dd46a8c);
              } else {
                  depositContract = IDepositContract(depositContract_);
              }
          }
          /**
           * @dev This contract will not accept direct ETH transactions.
           */
          receive() external payable {
              revert("AbyssEth2Depositor: do not send ETH directly here");
          }
          /**
           * @dev Function that allows to deposit up to 100 nodes at once.
           *
           * - pubkeys                - Array of BLS12-381 public keys.
           * - withdrawal_credentials - Array of commitments to a public keys for withdrawals.
           * - signatures             - Array of BLS12-381 signatures.
           * - deposit_data_roots     - Array of the SHA-256 hashes of the SSZ-encoded DepositData objects.
           */
          function deposit(
              bytes[] calldata pubkeys,
              bytes[] calldata withdrawal_credentials,
              bytes[] calldata signatures,
              bytes32[] calldata deposit_data_roots
          ) external payable whenNotPaused {
              uint256 nodesAmount = pubkeys.length;
              require(nodesAmount > 0 && nodesAmount <= 100, "AbyssEth2Depositor: you can deposit only 1 to 100 nodes per transaction");
              require(msg.value == collateral * nodesAmount, "AbyssEth2Depositor: the amount of ETH does not match the amount of nodes");
              require(
                  withdrawal_credentials.length == nodesAmount &&
                  signatures.length == nodesAmount &&
                  deposit_data_roots.length == nodesAmount,
                  "AbyssEth2Depositor: amount of parameters do no match");
              for (uint256 i = 0; i < nodesAmount; ++i) {
                  require(pubkeys[i].length == pubkeyLength, "AbyssEth2Depositor: wrong pubkey");
                  require(withdrawal_credentials[i].length == credentialsLength, "AbyssEth2Depositor: wrong withdrawal credentials");
                  require(signatures[i].length == signatureLength, "AbyssEth2Depositor: wrong signatures");
                  IDepositContract(address(depositContract)).deposit{value: collateral}(
                      pubkeys[i],
                      withdrawal_credentials[i],
                      signatures[i],
                      deposit_data_roots[i]
                  );
              }
              emit DepositEvent(msg.sender, nodesAmount);
          }
          /**
           * @dev Triggers stopped state.
           *
           * Requirements:
           *
           * - The contract must not be paused.
           */
          function pause() public onlyOwner {
            _pause();
          }
          /**
           * @dev Returns to normal state.
           *
           * Requirements:
           *
           * - The contract must be paused.
           */
          function unpause() public onlyOwner {
            _unpause();
          }
          event DepositEvent(address from, uint256 nodesAmount);
      }
      // SPDX-License-Identifier: CC0-1.0
      pragma solidity ^0.8.0;
      // 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);
      }
      // SPDX-License-Identifier: MIT
      pragma solidity ^0.8.0;
      import "../utils/Context.sol";
      /**
       * @dev Contract module which provides a basic access control mechanism, where
       * there is an account (an owner) that can be granted exclusive access to
       * specific functions.
       *
       * By default, the owner account will be the one that deploys the contract. This
       * can later be changed with {transferOwnership}.
       *
       * This module is used through inheritance. It will make available the modifier
       * `onlyOwner`, which can be applied to your functions to restrict their use to
       * the owner.
       */
      abstract contract Ownable is Context {
          address private _owner;
          event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
          /**
           * @dev Initializes the contract setting the deployer as the initial owner.
           */
          constructor () {
              address msgSender = _msgSender();
              _owner = msgSender;
              emit OwnershipTransferred(address(0), msgSender);
          }
          /**
           * @dev Returns the address of the current owner.
           */
          function owner() public view virtual returns (address) {
              return _owner;
          }
          /**
           * @dev Throws if called by any account other than the owner.
           */
          modifier onlyOwner() {
              require(owner() == _msgSender(), "Ownable: caller is not the owner");
              _;
          }
          /**
           * @dev Leaves the contract without owner. It will not be possible to call
           * `onlyOwner` functions anymore. Can only be called by the current owner.
           *
           * NOTE: Renouncing ownership will leave the contract without an owner,
           * thereby removing any functionality that is only available to the owner.
           */
          function renounceOwnership() public virtual onlyOwner {
              emit OwnershipTransferred(_owner, address(0));
              _owner = address(0);
          }
          /**
           * @dev Transfers ownership of the contract to a new account (`newOwner`).
           * Can only be called by the current owner.
           */
          function transferOwnership(address newOwner) public virtual onlyOwner {
              require(newOwner != address(0), "Ownable: new owner is the zero address");
              emit OwnershipTransferred(_owner, newOwner);
              _owner = newOwner;
          }
      }
      // SPDX-License-Identifier: MIT
      pragma solidity ^0.8.0;
      /*
       * @dev Provides information about the current execution context, including the
       * sender of the transaction and its data. While these are generally available
       * via msg.sender and msg.data, they should not be accessed in such a direct
       * manner, since when dealing with GSN meta-transactions the account sending and
       * paying for execution may not be the actual sender (as far as an application
       * is concerned).
       *
       * This contract is only required for intermediate, library-like contracts.
       */
      abstract contract Context {
          function _msgSender() internal view virtual returns (address) {
              return msg.sender;
          }
          function _msgData() internal view virtual returns (bytes calldata) {
              this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
              return msg.data;
          }
      }
      // SPDX-License-Identifier: MIT
      pragma solidity ^0.8.0;
      import "./Context.sol";
      /**
       * @dev Contract module which allows children to implement an emergency stop
       * mechanism that can be triggered by an authorized account.
       *
       * This module is used through inheritance. It will make available the
       * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
       * the functions of your contract. Note that they will not be pausable by
       * simply including this module, only once the modifiers are put in place.
       */
      abstract contract Pausable is Context {
          /**
           * @dev Emitted when the pause is triggered by `account`.
           */
          event Paused(address account);
          /**
           * @dev Emitted when the pause is lifted by `account`.
           */
          event Unpaused(address account);
          bool private _paused;
          /**
           * @dev Initializes the contract in unpaused state.
           */
          constructor () {
              _paused = false;
          }
          /**
           * @dev Returns true if the contract is paused, and false otherwise.
           */
          function paused() public view virtual returns (bool) {
              return _paused;
          }
          /**
           * @dev Modifier to make a function callable only when the contract is not paused.
           *
           * Requirements:
           *
           * - The contract must not be paused.
           */
          modifier whenNotPaused() {
              require(!paused(), "Pausable: paused");
              _;
          }
          /**
           * @dev Modifier to make a function callable only when the contract is paused.
           *
           * Requirements:
           *
           * - The contract must be paused.
           */
          modifier whenPaused() {
              require(paused(), "Pausable: not paused");
              _;
          }
          /**
           * @dev Triggers stopped state.
           *
           * Requirements:
           *
           * - The contract must not be paused.
           */
          function _pause() internal virtual whenNotPaused {
              _paused = true;
              emit Paused(_msgSender());
          }
          /**
           * @dev Returns to normal state.
           *
           * Requirements:
           *
           * - The contract must be paused.
           */
          function _unpause() internal virtual whenPaused {
              _paused = false;
              emit Unpaused(_msgSender());
          }
      }
      // SPDX-License-Identifier: MIT
      pragma solidity ^0.8.0;
      /**
       * @dev Contract module that helps prevent reentrant calls to a function.
       *
       * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
       * available, which can be applied to functions to make sure there are no nested
       * (reentrant) calls to them.
       *
       * Note that because there is a single `nonReentrant` guard, functions marked as
       * `nonReentrant` may not call one another. This can be worked around by making
       * those functions `private`, and then adding `external` `nonReentrant` entry
       * points to them.
       *
       * TIP: If you would like to learn more about reentrancy and alternative ways
       * to protect against it, check out our blog post
       * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
       */
      abstract contract ReentrancyGuard {
          // Booleans are more expensive than uint256 or any type that takes up a full
          // word because each write operation emits an extra SLOAD to first read the
          // slot's contents, replace the bits taken up by the boolean, and then write
          // back. This is the compiler's defense against contract upgrades and
          // pointer aliasing, and it cannot be disabled.
          // The values being non-zero value makes deployment a bit more expensive,
          // but in exchange the refund on every call to nonReentrant will be lower in
          // amount. Since refunds are capped to a percentage of the total
          // transaction's gas, it is best to keep them low in cases like this one, to
          // increase the likelihood of the full refund coming into effect.
          uint256 private constant _NOT_ENTERED = 1;
          uint256 private constant _ENTERED = 2;
          uint256 private _status;
          constructor () {
              _status = _NOT_ENTERED;
          }
          /**
           * @dev Prevents a contract from calling itself, directly or indirectly.
           * Calling a `nonReentrant` function from another `nonReentrant`
           * function is not supported. It is possible to prevent this from happening
           * by making the `nonReentrant` function external, and make it call a
           * `private` function that does the actual work.
           */
          modifier nonReentrant() {
              // On the first call to nonReentrant, _notEntered will be true
              require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
              // Any calls to nonReentrant after this point will fail
              _status = _ENTERED;
              _;
              // By storing the original value once again, a refund is triggered (see
              // https://eips.ethereum.org/EIPS/eip-2200)
              _status = _NOT_ENTERED;
          }
      }
      

      File 2 of 2: DepositContract
      // ┏━━━┓━┏┓━┏┓━━┏━━━┓━━┏━━━┓━━━━┏━━━┓━━━━━━━━━━━━━━━━━━━┏┓━━━━━┏━━━┓━━━━━━━━━┏┓━━━━━━━━━━━━━━┏┓━
      // ┃┏━━┛┏┛┗┓┃┃━━┃┏━┓┃━━┃┏━┓┃━━━━┗┓┏┓┃━━━━━━━━━━━━━━━━━━┏┛┗┓━━━━┃┏━┓┃━━━━━━━━┏┛┗┓━━━━━━━━━━━━┏┛┗┓
      // ┃┗━━┓┗┓┏┛┃┗━┓┗┛┏┛┃━━┃┃━┃┃━━━━━┃┃┃┃┏━━┓┏━━┓┏━━┓┏━━┓┏┓┗┓┏┛━━━━┃┃━┗┛┏━━┓┏━┓━┗┓┏┛┏━┓┏━━┓━┏━━┓┗┓┏┛
      // ┃┏━━┛━┃┃━┃┏┓┃┏━┛┏┛━━┃┃━┃┃━━━━━┃┃┃┃┃┏┓┃┃┏┓┃┃┏┓┃┃━━┫┣┫━┃┃━━━━━┃┃━┏┓┃┏┓┃┃┏┓┓━┃┃━┃┏┛┗━┓┃━┃┏━┛━┃┃━
      // ┃┗━━┓━┃┗┓┃┃┃┃┃┃┗━┓┏┓┃┗━┛┃━━━━┏┛┗┛┃┃┃━┫┃┗┛┃┃┗┛┃┣━━┃┃┃━┃┗┓━━━━┃┗━┛┃┃┗┛┃┃┃┃┃━┃┗┓┃┃━┃┗┛┗┓┃┗━┓━┃┗┓
      // ┗━━━┛━┗━┛┗┛┗┛┗━━━┛┗┛┗━━━┛━━━━┗━━━┛┗━━┛┃┏━┛┗━━┛┗━━┛┗┛━┗━┛━━━━┗━━━┛┗━━┛┗┛┗┛━┗━┛┗┛━┗━━━┛┗━━┛━┗━┛
      // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┃┃━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
      // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┗┛━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
      
      // 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];
          }
      }