Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Operator snapshot #91

Merged
merged 2 commits into from
Sep 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions contracts/ISSVNetwork.sol
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ interface ISSVNetwork {
event ValidatorRemoved(bytes publicKey, bytes32 podId);


/** errors */
error InvalidPublicKeyLength();
error OessDataStructureInvalid();
error ValidatorNotOwned();

/** errors */
// error validatorWithPublicKeyNotExist();
// error callerNotValidatorOwner();
Expand Down Expand Up @@ -119,6 +124,16 @@ interface ISSVNetwork {
*/
function updateOperatorFee(uint64 id, uint64 fee) external;

/**
* @dev Gets the operators current snapshot.
* @param id Operator's id.
* @return currentBlock the block that the snapshot is updated to
* @return index the index of the operator
* @return balance the current balance of the operator
*/
function operatorSnapshot(uint64 id) external view returns (uint64 currentBlock, uint64 index, uint64 balance);


/**
* @dev Registers a new validator.
* @param publicKey Validator public key.
Expand Down
70 changes: 34 additions & 36 deletions contracts/SSVNetwork.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ contract SSVNetwork is OwnableUpgradeable, ISSVNetwork {
uint64 fee;
uint64 validatorCount;

Snapshot earnings;
Snapshot snapshot;
}

struct DAO {
Expand Down Expand Up @@ -70,10 +70,6 @@ contract SSVNetwork is OwnableUpgradeable, ISSVNetwork {
uint64 constant LIQUIDATION_MIN_BLOCKS = 50;
// uint64 constant NETWORK_FEE_PER_BLOCK = 1;

/** errors */
error InvalidPublicKeyLength();
error OessDataStructureInvalid();
error ValidatorNotOwned();

DAO private _dao;
IERC20 private _token;
Expand All @@ -90,7 +86,7 @@ contract SSVNetwork is OwnableUpgradeable, ISSVNetwork {

lastOperatorId.increment();
operatorId = uint64(lastOperatorId.current());
_operators[operatorId] = Operator({ owner: msg.sender, earnings: Snapshot({ block: uint64(block.number), index: 0, balance: 0}), validatorCount: 0, fee: fee});
_operators[operatorId] = Operator({ owner: msg.sender, snapshot: Snapshot({ block: uint64(block.number), index: 0, balance: 0}), validatorCount: 0, fee: fee});
emit OperatorAdded(operatorId, msg.sender, encryptionPK);
}

Expand All @@ -100,7 +96,7 @@ contract SSVNetwork is OwnableUpgradeable, ISSVNetwork {

uint64 currentBlock = uint64(block.number);

operator.earnings = _updateOperatorEarnings(operator);
operator.snapshot = _getSnapshot(operator, currentBlock);
operator.fee = 0;
operator.validatorCount = 0;
_operators[operatorId] = operator;
Expand Down Expand Up @@ -138,7 +134,7 @@ contract SSVNetwork is OwnableUpgradeable, ISSVNetwork {
{
for (uint64 i = 0; i < operatorIds.length; ++i) {
Operator memory operator = _operators[operatorIds[i]];
operator.earnings = _updateOperatorEarnings(operator);
operator.snapshot = _getSnapshot(operator, uint64(block.number));
++operator.validatorCount;
_operators[operatorIds[i]] = operator;
}
Expand All @@ -151,7 +147,6 @@ contract SSVNetwork is OwnableUpgradeable, ISSVNetwork {
_dao = dao;
}

// TODO
require(!_liquidatable(pod.balance, pod.validatorCount, operatorIds), "account liquidatable");

_pods[keccak256(abi.encodePacked(msg.sender, clusterId))] = pod;
Expand Down Expand Up @@ -242,7 +237,7 @@ contract SSVNetwork is OwnableUpgradeable, ISSVNetwork {

for (uint64 i = 0; i < cluster.operatorIds.length; ++i) {
uint64 id = cluster.operatorIds[i];
_operators[id].earnings = _updateOperatorEarnings(_operators[id]);
_operators[id].snapshot = _getSnapshot(_operators[id], uint64(block.number));
--_operators[id].validatorCount;
}

Expand Down Expand Up @@ -306,6 +301,24 @@ contract SSVNetwork is OwnableUpgradeable, ISSVNetwork {

// TODO add external functions below to interface

// @dev external operators functions

function operatorSnapshot(uint64 id) external view returns (uint64 currentBlock, uint64 index, uint64 balance) {
Snapshot memory s = _getSnapshot(_operators[id], uint64(block.number));
return (s.block, s.index, s.balance);
}

// @dev internal operators functions

function _getSnapshot(Operator memory operator, uint64 currentBlock) private view returns (Snapshot memory) {
uint64 blockDiffFee = (currentBlock - operator.snapshot.block)* operator.fee;

operator.snapshot.index += blockDiffFee;
operator.snapshot.balance += blockDiffFee * operator.validatorCount;
operator.snapshot.block = currentBlock;

return operator.snapshot;
}

function _updateOperatorsValidatorMove(
uint64[] memory oldOperatorIds,
Expand All @@ -314,17 +327,18 @@ contract SSVNetwork is OwnableUpgradeable, ISSVNetwork {
) private {
uint64 oldIndex;
uint64 newIndex;
uint64 currentBlock = uint64(block.number);

while (oldIndex < oldOperatorIds.length && newIndex < newOperatorIds.length) {
if (oldOperatorIds[oldIndex] < newOperatorIds[newIndex]) {
Operator memory operator = _operators[oldOperatorIds[oldIndex]];
operator.earnings = _updateOperatorEarnings(operator);
operator.snapshot = _getSnapshot(operator, currentBlock);
operator.validatorCount -= validatorCount;
_operators[oldOperatorIds[oldIndex]] = operator;
++oldIndex;
} else if (newOperatorIds[newIndex] < oldOperatorIds[oldIndex]) {
Operator memory operator = _operators[newOperatorIds[newIndex]];
operator.earnings = _updateOperatorEarnings(operator);
operator.snapshot = _getSnapshot(operator, currentBlock);
operator.validatorCount += validatorCount;
_operators[newOperatorIds[newIndex]] = operator;
++newIndex;
Expand All @@ -336,15 +350,15 @@ contract SSVNetwork is OwnableUpgradeable, ISSVNetwork {

while (oldIndex < oldOperatorIds.length) {
Operator memory operator = _operators[oldOperatorIds[oldIndex]];
operator.earnings = _updateOperatorEarnings(operator);
operator.snapshot = _getSnapshot(operator, currentBlock);
operator.validatorCount -= validatorCount;
_operators[oldOperatorIds[oldIndex]] = operator;
++oldIndex;
}

while (newIndex < newOperatorIds.length) {
Operator memory operator = _operators[newOperatorIds[newIndex]];
operator.earnings = _updateOperatorEarnings(operator);
operator.snapshot = _getSnapshot(operator, currentBlock);
operator.validatorCount += validatorCount;
_operators[newOperatorIds[newIndex]] = operator;
++newIndex;
Expand All @@ -353,7 +367,7 @@ contract SSVNetwork is OwnableUpgradeable, ISSVNetwork {


function _setFee(Operator memory operator, uint64 fee) private returns (Operator memory) {
operator.earnings = _updateOperatorEarnings(operator);
operator.snapshot = _getSnapshot(operator, uint64(block.number));
operator.fee = fee;

return operator;
Expand All @@ -363,7 +377,7 @@ contract SSVNetwork is OwnableUpgradeable, ISSVNetwork {
uint64 currentBlock = uint64(block.number);
for (uint64 i = 0; i < operatorIds.length; ++i) {
Operator memory operator = _operators[operatorIds[i]];
operator.earnings = _updateOperatorEarnings(operator);
operator.snapshot = _getSnapshot(operator, uint64(block.number));
if (increase) {
++operator.validatorCount;
} else {
Expand Down Expand Up @@ -397,9 +411,7 @@ contract SSVNetwork is OwnableUpgradeable, ISSVNetwork {
return _ownerPodBalance(pod, _clusterCurrentIndex(clusterId));
}

function operatorEarningsOf(uint64 operatorId) external view returns (uint64) {
return _operatorCurrentEarnings(_operators[operatorId]);
}


/**
* @dev Validates the params for a validator.
Expand Down Expand Up @@ -446,13 +458,6 @@ contract SSVNetwork is OwnableUpgradeable, ISSVNetwork {
return key;
}

function _updateOperatorEarnings(Operator memory operator) private returns (Snapshot memory) {
operator.earnings.index = _operatorCurrentIndex(operator);
operator.earnings.balance = _operatorCurrentEarnings(operator);
operator.earnings.block = uint64(block.number);

return operator.earnings;
}

function _updateDAOEarnings(DAO memory dao) private returns (DAO memory) {
dao.earnings.balance = _networkTotalEarnings(dao);
Expand All @@ -461,12 +466,6 @@ contract SSVNetwork is OwnableUpgradeable, ISSVNetwork {
return dao;
}

// TODO
// no connection with owner address
function _operatorCurrentEarnings(Operator memory operator) private view returns (uint64) {
return operator.earnings.balance + (uint64(block.number) - operator.earnings.block) * operator.validatorCount * operator.fee;
}

function _extractOperators(uint64[] memory operatorIds) private view returns (Operator[] memory) {
Operator[] memory operators = new Operator[](operatorIds.length);
for (uint64 i = 0; i < operatorIds.length; ++i) {
Expand All @@ -485,14 +484,13 @@ contract SSVNetwork is OwnableUpgradeable, ISSVNetwork {

function _clusterCurrentIndex(bytes32 podId) private view returns (uint64 podIndex) {
Cluster memory cluster = _clusters[podId];
uint64 currentBlock = uint64(block.number);
for (uint64 i = 0; i < cluster.operatorIds.length; ++i) {
podIndex += _operatorCurrentIndex(_operators[cluster.operatorIds[i]]);
Snapshot memory s = _operators[cluster.operatorIds[i]].snapshot;
podIndex += s.index + (currentBlock - s.block) * _operators[cluster.operatorIds[i]].fee;
}
}

function _operatorCurrentIndex(Operator memory operator) private view returns (uint64) {
return operator.earnings.index + (uint64(block.number) - operator.earnings.block) * operator.fee;
}

function _ownerPodBalance(Pod memory pod, uint64 currentPodIndex) private view returns (uint64) {
return pod.balance - (currentPodIndex - pod.usage.index) * pod.validatorCount;
Expand Down
2 changes: 1 addition & 1 deletion test/vadimToUpdate.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ async function log({ action='', operatorIds = [], groupIds = [] }) {
for (const id of operatorIds) {
console.log(
`> operator #${id}`,
'balance', await deployedSSVNetworkContract.operatorEarningsOf(id),
'balance', (await deployedSSVNetworkContract.operatorSnapshot(id)).balance,
);
}
}
Expand Down