{"compiler":{"version":"0.6.11+commit.5ef660b1"},"language":"Solidity","output":{"abi":[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"pubkey","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"withdrawal_credentials","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"amount","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"signature","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"index","type":"bytes"}],"name":"DepositEvent","type":"event"},{"inputs":[{"internalType":"bytes","name":"pubkey","type":"bytes"},{"internalType":"bytes","name":"withdrawal_credentials","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes32","name":"deposit_data_root","type":"bytes32"}],"name":"deposit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"get_deposit_count","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"get_deposit_root","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"}],"devdoc":{"kind":"dev","methods":{"deposit(bytes,bytes,bytes,bytes32)":{"params":{"deposit_data_root":"The SHA-256 hash of the SSZ-encoded DepositData object. Used as a protection against malformed input.","pubkey":"A BLS12-381 public key.","signature":"A BLS12-381 signature.","withdrawal_credentials":"Commitment to a public key for withdrawals."}},"get_deposit_count()":{"returns":{"_0":"The deposit count encoded as a little endian 64-bit number."}},"get_deposit_root()":{"returns":{"_0":"The deposit root hash."}},"supportsInterface(bytes4)":{"details":"Interface identification is specified in ERC-165. This function  uses less than 30,000 gas.","params":{"interfaceId":"The interface identifier, as specified in ERC-165"},"returns":{"_0":"`true` if the contract implements `interfaceId` and  `interfaceId` is not 0xffffffff, `false` otherwise"}}},"version":1},"userdoc":{"events":{"DepositEvent(bytes,bytes,bytes,bytes,bytes)":{"notice":"A processed deposit event."}},"kind":"user","methods":{"deposit(bytes,bytes,bytes,bytes32)":{"notice":"Submit a Phase 0 DepositData object."},"get_deposit_count()":{"notice":"Query the current deposit count."},"get_deposit_root()":{"notice":"Query the current deposit root hash."},"supportsInterface(bytes4)":{"notice":"Query if a contract implements an interface"}},"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","version":1}},"settings":{"compilationTarget":{"deposit_contract.sol":"DepositContract"},"evmVersion":"istanbul","libraries":{},"metadata":{"bytecodeHash":"ipfs","useLiteralContent":true},"optimizer":{"enabled":true,"runs":5000000},"remappings":[]},"sources":{"deposit_contract.sol":{"content":"// \u250f\u2501\u2501\u2501\u2513\u2501\u250f\u2513\u2501\u250f\u2513\u2501\u2501\u250f\u2501\u2501\u2501\u2513\u2501\u2501\u250f\u2501\u2501\u2501\u2513\u2501\u2501\u2501\u2501\u250f\u2501\u2501\u2501\u2513\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u250f\u2513\u2501\u2501\u2501\u2501\u2501\u250f\u2501\u2501\u2501\u2513\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u250f\u2513\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u250f\u2513\u2501\n// \u2503\u250f\u2501\u2501\u251b\u250f\u251b\u2517\u2513\u2503\u2503\u2501\u2501\u2503\u250f\u2501\u2513\u2503\u2501\u2501\u2503\u250f\u2501\u2513\u2503\u2501\u2501\u2501\u2501\u2517\u2513\u250f\u2513\u2503\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u250f\u251b\u2517\u2513\u2501\u2501\u2501\u2501\u2503\u250f\u2501\u2513\u2503\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u250f\u251b\u2517\u2513\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u250f\u251b\u2517\u2513\n// \u2503\u2517\u2501\u2501\u2513\u2517\u2513\u250f\u251b\u2503\u2517\u2501\u2513\u2517\u251b\u250f\u251b\u2503\u2501\u2501\u2503\u2503\u2501\u2503\u2503\u2501\u2501\u2501\u2501\u2501\u2503\u2503\u2503\u2503\u250f\u2501\u2501\u2513\u250f\u2501\u2501\u2513\u250f\u2501\u2501\u2513\u250f\u2501\u2501\u2513\u250f\u2513\u2517\u2513\u250f\u251b\u2501\u2501\u2501\u2501\u2503\u2503\u2501\u2517\u251b\u250f\u2501\u2501\u2513\u250f\u2501\u2513\u2501\u2517\u2513\u250f\u251b\u250f\u2501\u2513\u250f\u2501\u2501\u2513\u2501\u250f\u2501\u2501\u2513\u2517\u2513\u250f\u251b\n// \u2503\u250f\u2501\u2501\u251b\u2501\u2503\u2503\u2501\u2503\u250f\u2513\u2503\u250f\u2501\u251b\u250f\u251b\u2501\u2501\u2503\u2503\u2501\u2503\u2503\u2501\u2501\u2501\u2501\u2501\u2503\u2503\u2503\u2503\u2503\u250f\u2513\u2503\u2503\u250f\u2513\u2503\u2503\u250f\u2513\u2503\u2503\u2501\u2501\u252b\u2523\u252b\u2501\u2503\u2503\u2501\u2501\u2501\u2501\u2501\u2503\u2503\u2501\u250f\u2513\u2503\u250f\u2513\u2503\u2503\u250f\u2513\u2513\u2501\u2503\u2503\u2501\u2503\u250f\u251b\u2517\u2501\u2513\u2503\u2501\u2503\u250f\u2501\u251b\u2501\u2503\u2503\u2501\n// \u2503\u2517\u2501\u2501\u2513\u2501\u2503\u2517\u2513\u2503\u2503\u2503\u2503\u2503\u2503\u2517\u2501\u2513\u250f\u2513\u2503\u2517\u2501\u251b\u2503\u2501\u2501\u2501\u2501\u250f\u251b\u2517\u251b\u2503\u2503\u2503\u2501\u252b\u2503\u2517\u251b\u2503\u2503\u2517\u251b\u2503\u2523\u2501\u2501\u2503\u2503\u2503\u2501\u2503\u2517\u2513\u2501\u2501\u2501\u2501\u2503\u2517\u2501\u251b\u2503\u2503\u2517\u251b\u2503\u2503\u2503\u2503\u2503\u2501\u2503\u2517\u2513\u2503\u2503\u2501\u2503\u2517\u251b\u2517\u2513\u2503\u2517\u2501\u2513\u2501\u2503\u2517\u2513\n// \u2517\u2501\u2501\u2501\u251b\u2501\u2517\u2501\u251b\u2517\u251b\u2517\u251b\u2517\u2501\u2501\u2501\u251b\u2517\u251b\u2517\u2501\u2501\u2501\u251b\u2501\u2501\u2501\u2501\u2517\u2501\u2501\u2501\u251b\u2517\u2501\u2501\u251b\u2503\u250f\u2501\u251b\u2517\u2501\u2501\u251b\u2517\u2501\u2501\u251b\u2517\u251b\u2501\u2517\u2501\u251b\u2501\u2501\u2501\u2501\u2517\u2501\u2501\u2501\u251b\u2517\u2501\u2501\u251b\u2517\u251b\u2517\u251b\u2501\u2517\u2501\u251b\u2517\u251b\u2501\u2517\u2501\u2501\u2501\u251b\u2517\u2501\u2501\u251b\u2501\u2517\u2501\u251b\n// \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2503\u2503\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n// \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2517\u251b\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\n// SPDX-License-Identifier: CC0-1.0\n\npragma solidity 0.6.11;\n\n// This interface is designed to be compatible with the Vyper version.\n/// @notice This is the Ethereum 2.0 deposit contract interface.\n/// For more information see the Phase 0 specification under https://github.com/ethereum/eth2.0-specs\ninterface IDepositContract {\n    /// @notice A processed deposit event.\n    event DepositEvent(\n        bytes pubkey,\n        bytes withdrawal_credentials,\n        bytes amount,\n        bytes signature,\n        bytes index\n    );\n\n    /// @notice Submit a Phase 0 DepositData object.\n    /// @param pubkey A BLS12-381 public key.\n    /// @param withdrawal_credentials Commitment to a public key for withdrawals.\n    /// @param signature A BLS12-381 signature.\n    /// @param deposit_data_root The SHA-256 hash of the SSZ-encoded DepositData object.\n    /// Used as a protection against malformed input.\n    function deposit(\n        bytes calldata pubkey,\n        bytes calldata withdrawal_credentials,\n        bytes calldata signature,\n        bytes32 deposit_data_root\n    ) external payable;\n\n    /// @notice Query the current deposit root hash.\n    /// @return The deposit root hash.\n    function get_deposit_root() external view returns (bytes32);\n\n    /// @notice Query the current deposit count.\n    /// @return The deposit count encoded as a little endian 64-bit number.\n    function get_deposit_count() external view returns (bytes memory);\n}\n\n// Based on official specification in https://eips.ethereum.org/EIPS/eip-165\ninterface ERC165 {\n    /// @notice Query if a contract implements an interface\n    /// @param interfaceId The interface identifier, as specified in ERC-165\n    /// @dev Interface identification is specified in ERC-165. This function\n    ///  uses less than 30,000 gas.\n    /// @return `true` if the contract implements `interfaceId` and\n    ///  `interfaceId` is not 0xffffffff, `false` otherwise\n    function supportsInterface(bytes4 interfaceId) external pure returns (bool);\n}\n\n// This is a rewrite of the Vyper Eth2.0 deposit contract in Solidity.\n// It tries to stay as close as possible to the original source code.\n/// @notice This is the Ethereum 2.0 deposit contract interface.\n/// For more information see the Phase 0 specification under https://github.com/ethereum/eth2.0-specs\ncontract DepositContract is IDepositContract, ERC165 {\n    uint constant DEPOSIT_CONTRACT_TREE_DEPTH = 32;\n    // NOTE: this also ensures `deposit_count` will fit into 64-bits\n    uint constant MAX_DEPOSIT_COUNT = 2**DEPOSIT_CONTRACT_TREE_DEPTH - 1;\n\n    bytes32[DEPOSIT_CONTRACT_TREE_DEPTH] branch;\n    uint256 deposit_count;\n\n    bytes32[DEPOSIT_CONTRACT_TREE_DEPTH] zero_hashes;\n\n    constructor() public {\n        // Compute hashes in empty sparse Merkle tree\n        for (uint height = 0; height < DEPOSIT_CONTRACT_TREE_DEPTH - 1; height++)\n            zero_hashes[height + 1] = sha256(abi.encodePacked(zero_hashes[height], zero_hashes[height]));\n    }\n\n    function get_deposit_root() override external view returns (bytes32) {\n        bytes32 node;\n        uint size = deposit_count;\n        for (uint height = 0; height < DEPOSIT_CONTRACT_TREE_DEPTH; height++) {\n            if ((size & 1) == 1)\n                node = sha256(abi.encodePacked(branch[height], node));\n            else\n                node = sha256(abi.encodePacked(node, zero_hashes[height]));\n            size /= 2;\n        }\n        return sha256(abi.encodePacked(\n            node,\n            to_little_endian_64(uint64(deposit_count)),\n            bytes24(0)\n        ));\n    }\n\n    function get_deposit_count() override external view returns (bytes memory) {\n        return to_little_endian_64(uint64(deposit_count));\n    }\n\n    function deposit(\n        bytes calldata pubkey,\n        bytes calldata withdrawal_credentials,\n        bytes calldata signature,\n        bytes32 deposit_data_root\n    ) override external payable {\n        // Extended ABI length checks since dynamic types are used.\n        require(pubkey.length == 48, \"DepositContract: invalid pubkey length\");\n        require(withdrawal_credentials.length == 32, \"DepositContract: invalid withdrawal_credentials length\");\n        require(signature.length == 96, \"DepositContract: invalid signature length\");\n\n        // Check deposit amount\n        require(msg.value >= 1 ether, \"DepositContract: deposit value too low\");\n        require(msg.value % 1 gwei == 0, \"DepositContract: deposit value not multiple of gwei\");\n        uint deposit_amount = msg.value / 1 gwei;\n        require(deposit_amount <= type(uint64).max, \"DepositContract: deposit value too high\");\n\n        // Emit `DepositEvent` log\n        bytes memory amount = to_little_endian_64(uint64(deposit_amount));\n        emit DepositEvent(\n            pubkey,\n            withdrawal_credentials,\n            amount,\n            signature,\n            to_little_endian_64(uint64(deposit_count))\n        );\n\n        // Compute deposit data root (`DepositData` hash tree root)\n        bytes32 pubkey_root = sha256(abi.encodePacked(pubkey, bytes16(0)));\n        bytes32 signature_root = sha256(abi.encodePacked(\n            sha256(abi.encodePacked(signature[:64])),\n            sha256(abi.encodePacked(signature[64:], bytes32(0)))\n        ));\n        bytes32 node = sha256(abi.encodePacked(\n            sha256(abi.encodePacked(pubkey_root, withdrawal_credentials)),\n            sha256(abi.encodePacked(amount, bytes24(0), signature_root))\n        ));\n\n        // Verify computed and expected deposit data roots match\n        require(node == deposit_data_root, \"DepositContract: reconstructed DepositData does not match supplied deposit_data_root\");\n\n        // Avoid overflowing the Merkle tree (and prevent edge case in computing `branch`)\n        require(deposit_count < MAX_DEPOSIT_COUNT, \"DepositContract: merkle tree full\");\n\n        // Add deposit data root to Merkle tree (update a single `branch` node)\n        deposit_count += 1;\n        uint size = deposit_count;\n        for (uint height = 0; height < DEPOSIT_CONTRACT_TREE_DEPTH; height++) {\n            if ((size & 1) == 1) {\n                branch[height] = node;\n                return;\n            }\n            node = sha256(abi.encodePacked(branch[height], node));\n            size /= 2;\n        }\n        // As the loop should always end prematurely with the `return` statement,\n        // this code should be unreachable. We assert `false` just to be safe.\n        assert(false);\n    }\n\n    function supportsInterface(bytes4 interfaceId) override external pure returns (bool) {\n        return interfaceId == type(ERC165).interfaceId || interfaceId == type(IDepositContract).interfaceId;\n    }\n\n    function to_little_endian_64(uint64 value) internal pure returns (bytes memory ret) {\n        ret = new bytes(8);\n        bytes8 bytesValue = bytes8(value);\n        // Byteswapping during copying to bytes.\n        ret[0] = bytesValue[7];\n        ret[1] = bytesValue[6];\n        ret[2] = bytesValue[5];\n        ret[3] = bytesValue[4];\n        ret[4] = bytesValue[3];\n        ret[5] = bytesValue[2];\n        ret[6] = bytesValue[1];\n        ret[7] = bytesValue[0];\n    }\n}\n","keccak256":"0xeb4884395e470268e1ff14dca32e7a030425557a23cb16013c4d25914fd1e4a1","license":"CC0-1.0"}},"version":1}