Last active
July 5, 2023 17:38
-
-
Save androolloyd/555534b6d29759c0963c1dea1a5097db to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: Apache-2.0 | |
pragma solidity 0.6.8; | |
library SafeMath { | |
/** | |
* @dev Returns the addition of two unsigned integers, reverting on | |
* overflow. | |
* | |
* Counterpart to Solidity's `+` operator. | |
* | |
* Requirements: | |
* | |
* - Addition cannot overflow. | |
*/ | |
function add(uint256 a, uint256 b) internal pure returns (uint256) { | |
uint256 c = a + b; | |
require(c >= a, "SafeMath: addition overflow"); | |
return c; | |
} | |
/** | |
* @dev Returns the subtraction of two unsigned integers, reverting on | |
* overflow (when the result is negative). | |
* | |
* Counterpart to Solidity's `-` operator. | |
* | |
* Requirements: | |
* | |
* - Subtraction cannot overflow. | |
*/ | |
function sub(uint256 a, uint256 b) internal pure returns (uint256) { | |
return sub(a, b, "SafeMath: subtraction overflow"); | |
} | |
/** | |
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on | |
* overflow (when the result is negative). | |
* | |
* Counterpart to Solidity's `-` operator. | |
* | |
* Requirements: | |
* | |
* - Subtraction cannot overflow. | |
*/ | |
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b <= a, errorMessage); | |
uint256 c = a - b; | |
return c; | |
} | |
/** | |
* @dev Returns the multiplication of two unsigned integers, reverting on | |
* overflow. | |
* | |
* Counterpart to Solidity's `*` operator. | |
* | |
* Requirements: | |
* | |
* - Multiplication cannot overflow. | |
*/ | |
function mul(uint256 a, uint256 b) internal pure returns (uint256) { | |
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the | |
// benefit is lost if 'b' is also tested. | |
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 | |
if (a == 0) { | |
return 0; | |
} | |
uint256 c = a * b; | |
require(c / a == b, "SafeMath: multiplication overflow"); | |
return c; | |
} | |
/** | |
* @dev Returns the integer division of two unsigned integers. Reverts on | |
* division by zero. The result is rounded towards zero. | |
* | |
* Counterpart to Solidity's `/` operator. Note: this function uses a | |
* `revert` opcode (which leaves remaining gas untouched) while Solidity | |
* uses an invalid opcode to revert (consuming all remaining gas). | |
* | |
* Requirements: | |
* | |
* - The divisor cannot be zero. | |
*/ | |
function div(uint256 a, uint256 b) internal pure returns (uint256) { | |
return div(a, b, "SafeMath: division by zero"); | |
} | |
/** | |
* @dev Returns the integer division of two unsigned integers. Reverts with custom message on | |
* division by zero. The result is rounded towards zero. | |
* | |
* Counterpart to Solidity's `/` operator. Note: this function uses a | |
* `revert` opcode (which leaves remaining gas untouched) while Solidity | |
* uses an invalid opcode to revert (consuming all remaining gas). | |
* | |
* Requirements: | |
* | |
* - The divisor cannot be zero. | |
*/ | |
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b > 0, errorMessage); | |
uint256 c = a / b; | |
// assert(a == b * c + a % b); // There is no case in which this doesn't hold | |
return c; | |
} | |
/** | |
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), | |
* Reverts when dividing by zero. | |
* | |
* Counterpart to Solidity's `%` operator. This function uses a `revert` | |
* opcode (which leaves remaining gas untouched) while Solidity uses an | |
* invalid opcode to revert (consuming all remaining gas). | |
* | |
* Requirements: | |
* | |
* - The divisor cannot be zero. | |
*/ | |
function mod(uint256 a, uint256 b) internal pure returns (uint256) { | |
return mod(a, b, "SafeMath: modulo by zero"); | |
} | |
/** | |
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), | |
* Reverts with custom message when dividing by zero. | |
* | |
* Counterpart to Solidity's `%` operator. This function uses a `revert` | |
* opcode (which leaves remaining gas untouched) while Solidity uses an | |
* invalid opcode to revert (consuming all remaining gas). | |
* | |
* Requirements: | |
* | |
* - The divisor cannot be zero. | |
*/ | |
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b != 0, errorMessage); | |
return a % b; | |
} | |
} | |
// Deposit contract interface | |
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); | |
} | |
contract BatchDeposit { | |
using SafeMath for uint256; | |
address constant depositContract = address(0x00000000219ab540356cbb839cbe05303d7705fa); | |
uint32 constant PUBKEY_LENGTH = 48; | |
uint32 constant SIGNATURE_LENGTH = 96; | |
uint32 constant CREDENTIALS_LENGTH = 32; | |
uint8 constant MAX_VALIDATORS = 100; | |
uint constant DEPOSIT_AMOUNT = 32 ether; | |
/** | |
* @dev Performs a batch deposit | |
*/ | |
function batchDeposit( | |
bytes calldata pubkeys, | |
bytes calldata withdrawal_credentials, | |
bytes calldata signatures, | |
bytes32[] calldata deposit_data_roots | |
) | |
external payable | |
{ | |
// sanity checks | |
require(msg.value >= DEPOSIT_AMOUNT, "BatchDeposit: Amount is too low"); | |
require(pubkeys.length >= PUBKEY_LENGTH, "BatchDeposit: You should deposit at least one validator"); | |
require(pubkeys.length.mod(PUBKEY_LENGTH) == 0, "BatchDeposit: Invalid pubkey length"); | |
require(pubkeys.length <= PUBKEY_LENGTH * MAX_VALIDATORS, "BatchDeposit: You can deposit max 100 validators at a time"); | |
require(signatures.length >= SIGNATURE_LENGTH, "DepositContract: Invalid signature length"); | |
require(signatures.length.mod(SIGNATURE_LENGTH) == 0, "BatchDeposit: Invalid signature length"); | |
require(withdrawal_credentials.length == CREDENTIALS_LENGTH, "BatchDeposit: Invalid withdrawal_credentials length"); | |
uint32 pubkeyCount = uint32(pubkeys.length.div(PUBKEY_LENGTH)); | |
require( | |
pubkeyCount == signatures.length.div(SIGNATURE_LENGTH) && pubkeyCount == deposit_data_roots.length, | |
"BatchDeposit: Data counts don't match" | |
); | |
uint256 expectedAmount = DEPOSIT_AMOUNT.mul(pubkeyCount); | |
require(msg.value == expectedAmount, "BatchDeposit: Amount is not aligned with pubkeys number"); | |
for (uint32 i = 0; i < pubkeyCount; ++i) { | |
bytes memory pubkey = bytes(pubkeys[i*PUBKEY_LENGTH:(i+1)*PUBKEY_LENGTH]); | |
bytes memory signature = bytes(signatures[i*SIGNATURE_LENGTH:(i+1)*SIGNATURE_LENGTH]); | |
IDepositContract(depositContract).deposit{value: DEPOSIT_AMOUNT}( | |
pubkey, | |
withdrawal_credentials, | |
signature, | |
deposit_data_roots[i] | |
); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment