2018-12-19 01:49:02 +00:00
|
|
|
pragma solidity ^0.5.1;
|
2018-11-30 15:12:23 +00:00
|
|
|
|
2019-01-01 16:10:56 +00:00
|
|
|
import "./SafeMath.sol";
|
2018-07-12 17:00:37 +00:00
|
|
|
contract ValidatorRegistration {
|
2018-11-30 15:12:23 +00:00
|
|
|
|
2019-01-16 14:01:21 +00:00
|
|
|
event Deposit(
|
2018-11-30 15:12:23 +00:00
|
|
|
bytes indexed previousReceiptRoot,
|
|
|
|
bytes data,
|
2019-01-16 14:01:21 +00:00
|
|
|
bytes merkleTreeIndex
|
2018-11-30 15:12:23 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
event ChainStart(
|
|
|
|
bytes indexed receiptRoot,
|
|
|
|
bytes time
|
2018-07-12 17:00:37 +00:00
|
|
|
);
|
|
|
|
|
2018-11-30 15:12:23 +00:00
|
|
|
uint public constant DEPOSIT_SIZE = 32 ether;
|
2018-12-19 01:49:02 +00:00
|
|
|
// 8 is for our local test net. 2.0 spec is 2**14 == 16384
|
|
|
|
uint public constant DEPOSITS_FOR_CHAIN_START = 8; // 2**14
|
2018-11-30 15:12:23 +00:00
|
|
|
uint public constant MIN_TOPUP_SIZE = 1 ether;
|
|
|
|
uint public constant GWEI_PER_ETH = 10 ** 9;
|
|
|
|
// Setting MERKLE_TREE_DEPTH to 16 instead of 32 due to gas limit
|
|
|
|
uint public constant MERKLE_TREE_DEPTH = 16;
|
|
|
|
uint public constant SECONDS_PER_DAY = 86400;
|
2018-08-02 11:07:04 +00:00
|
|
|
|
2019-01-16 14:01:21 +00:00
|
|
|
mapping (uint => bytes) public depositTree;
|
|
|
|
uint public depositCount;
|
2018-12-19 01:49:02 +00:00
|
|
|
uint public fullDepositCount;
|
2019-01-16 14:01:21 +00:00
|
|
|
|
2018-07-12 17:00:37 +00:00
|
|
|
|
2019-01-01 16:10:56 +00:00
|
|
|
using SafeMath for uint256;
|
|
|
|
|
|
|
|
|
2018-11-30 15:12:23 +00:00
|
|
|
// When users wish to become a validator by moving ETH from
|
|
|
|
// 1.0 chian to the 2.0 chain, they should call this function
|
|
|
|
// sending along DEPOSIT_SIZE ETH and providing depositParams
|
|
|
|
// as a simple serialize'd DepositParams object of the following
|
|
|
|
// form:
|
|
|
|
// {
|
2018-12-19 01:49:02 +00:00
|
|
|
// 'pubkey': 'uint384',
|
|
|
|
// 'proof_of_possession': ['uint384'],
|
2018-11-30 15:12:23 +00:00
|
|
|
// 'withdrawal_credentials`: 'hash32',
|
|
|
|
// 'randao_commitment`: 'hash32'
|
|
|
|
// }
|
2018-07-12 17:00:37 +00:00
|
|
|
function deposit(
|
2018-12-19 01:49:02 +00:00
|
|
|
bytes memory depositParams
|
2018-11-06 21:13:46 +00:00
|
|
|
)
|
|
|
|
public
|
|
|
|
payable
|
|
|
|
{
|
2018-08-06 15:12:55 +00:00
|
|
|
require(
|
2018-11-30 15:12:23 +00:00
|
|
|
msg.value <= DEPOSIT_SIZE,
|
|
|
|
"Deposit can't be greater than DEPOSIT_SIZE."
|
2018-08-06 15:12:55 +00:00
|
|
|
);
|
|
|
|
require(
|
2018-11-30 15:12:23 +00:00
|
|
|
msg.value >= MIN_TOPUP_SIZE,
|
|
|
|
"Deposit can't be lesser than MIN_TOPUP_SIZE."
|
2018-11-06 21:13:46 +00:00
|
|
|
);
|
2018-12-19 01:49:02 +00:00
|
|
|
|
2019-01-16 14:01:21 +00:00
|
|
|
uint index = depositCount + 2 ** MERKLE_TREE_DEPTH;
|
2018-12-19 01:49:02 +00:00
|
|
|
bytes memory msgGweiInBytes8 = abi.encodePacked(uint64(msg.value/GWEI_PER_ETH));
|
|
|
|
bytes memory timeStampInBytes8 = abi.encodePacked(uint64(block.timestamp));
|
|
|
|
bytes memory depositData = abi.encodePacked(msgGweiInBytes8, timeStampInBytes8, depositParams);
|
2019-01-16 14:01:21 +00:00
|
|
|
bytes memory merkleTreeIndex = abi.encodePacked(uint64(index));
|
2018-12-19 01:49:02 +00:00
|
|
|
|
2019-01-16 14:01:21 +00:00
|
|
|
emit Deposit(depositTree[1], depositData, merkleTreeIndex);
|
2018-12-19 01:49:02 +00:00
|
|
|
|
2019-01-16 14:01:21 +00:00
|
|
|
depositTree[index] = abi.encodePacked(keccak256(depositData));
|
2018-12-19 01:49:02 +00:00
|
|
|
for (uint i = 0; i < MERKLE_TREE_DEPTH; i++) {
|
|
|
|
index = index / 2;
|
2019-01-16 14:01:21 +00:00
|
|
|
depositTree[index] = abi.encodePacked(keccak256(abi.encodePacked(depositTree[index * 2], depositTree[index * 2 + 1])));
|
2018-11-30 15:12:23 +00:00
|
|
|
}
|
2018-12-19 01:49:02 +00:00
|
|
|
|
2019-01-16 14:01:21 +00:00
|
|
|
depositCount++;
|
2018-12-19 01:49:02 +00:00
|
|
|
if (msg.value == DEPOSIT_SIZE) {
|
|
|
|
fullDepositCount++;
|
2018-11-06 21:13:46 +00:00
|
|
|
|
2018-12-19 01:49:02 +00:00
|
|
|
// When ChainStart log publishes, beacon chain node initializes the chain and use timestampDayBoundry
|
|
|
|
// as genesis time.
|
|
|
|
if (fullDepositCount == DEPOSITS_FOR_CHAIN_START) {
|
2019-01-01 16:10:56 +00:00
|
|
|
uint timestampDayBoundry = block.timestamp.sub(block.timestamp).mod(SECONDS_PER_DAY).add(SECONDS_PER_DAY);
|
2018-12-19 01:49:02 +00:00
|
|
|
bytes memory timestampDayBoundryBytes = abi.encodePacked(uint64(timestampDayBoundry));
|
2019-01-16 14:01:21 +00:00
|
|
|
emit ChainStart(depositTree[1], timestampDayBoundryBytes);
|
2018-12-19 01:49:02 +00:00
|
|
|
}
|
2018-11-30 15:12:23 +00:00
|
|
|
}
|
|
|
|
}
|
2018-07-12 17:00:37 +00:00
|
|
|
|
2019-01-16 14:01:21 +00:00
|
|
|
function getDepositRoot() public view returns (bytes memory) {
|
|
|
|
return depositTree[1];
|
2018-11-30 15:12:23 +00:00
|
|
|
}
|
2018-08-02 11:07:04 +00:00
|
|
|
}
|