From 03fc0d829cb48bacdbba1643548d7fe45853dcb4 Mon Sep 17 00:00:00 2001 From: Lior Rutenberg Date: Thu, 1 Sep 2022 14:27:30 +0300 Subject: [PATCH 1/2] rename eraningins to snapshot + gas improvment --- contracts/ISSVNetwork.sol | 5 +++ contracts/SSVNetwork.sol | 64 ++++++++++++++++++--------------------- test/vadimToUpdate.js | 2 +- 3 files changed, 35 insertions(+), 36 deletions(-) diff --git a/contracts/ISSVNetwork.sol b/contracts/ISSVNetwork.sol index 4abd4535..078795cd 100644 --- a/contracts/ISSVNetwork.sol +++ b/contracts/ISSVNetwork.sol @@ -75,6 +75,11 @@ interface ISSVNetwork { event ValidatorRemoved(bytes publicKey, bytes32 podId); + /** errors */ + error InvalidPublicKeyLength(); + error OessDataStructureInvalid(); + error ValidatorNotOwned(); + /** errors */ // error validatorWithPublicKeyNotExist(); // error callerNotValidatorOwner(); diff --git a/contracts/SSVNetwork.sol b/contracts/SSVNetwork.sol index eb4ac99c..c13d1cc1 100644 --- a/contracts/SSVNetwork.sol +++ b/contracts/SSVNetwork.sol @@ -27,7 +27,7 @@ contract SSVNetwork is OwnableUpgradeable, ISSVNetwork { uint64 fee; uint64 validatorCount; - Snapshot earnings; + Snapshot snapshot; } struct DAO { @@ -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; @@ -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); } @@ -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; @@ -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; } @@ -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; @@ -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; } @@ -307,6 +302,18 @@ contract SSVNetwork is OwnableUpgradeable, ISSVNetwork { // TODO add external functions below to interface + // @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, uint64[] memory newOperatorIds, @@ -314,17 +321,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; @@ -336,7 +344,7 @@ 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; @@ -344,7 +352,7 @@ contract SSVNetwork is OwnableUpgradeable, ISSVNetwork { 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; @@ -353,7 +361,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; @@ -363,7 +371,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 { @@ -397,8 +405,8 @@ contract SSVNetwork is OwnableUpgradeable, ISSVNetwork { return _ownerPodBalance(pod, _clusterCurrentIndex(clusterId)); } - function operatorEarningsOf(uint64 operatorId) external view returns (uint64) { - return _operatorCurrentEarnings(_operators[operatorId]); + function operatorSnapshot(uint64 operatorId) external view returns (Snapshot memory) { + return _getSnapshot(_operators[operatorId], uint64(block.number)); } /** @@ -446,13 +454,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); @@ -461,12 +462,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) { @@ -485,14 +480,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; diff --git a/test/vadimToUpdate.js b/test/vadimToUpdate.js index 564afee7..8eec612a 100644 --- a/test/vadimToUpdate.js +++ b/test/vadimToUpdate.js @@ -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, ); } } From 067e558e7ac2e5a467af27836d0ee9cf1a0184db Mon Sep 17 00:00:00 2001 From: Lior Rutenberg Date: Thu, 1 Sep 2022 14:42:58 +0300 Subject: [PATCH 2/2] operatorSnapshot to interface --- contracts/ISSVNetwork.sol | 10 ++++++++++ contracts/SSVNetwork.sol | 10 +++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/contracts/ISSVNetwork.sol b/contracts/ISSVNetwork.sol index 078795cd..bb1060d9 100644 --- a/contracts/ISSVNetwork.sol +++ b/contracts/ISSVNetwork.sol @@ -124,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. diff --git a/contracts/SSVNetwork.sol b/contracts/SSVNetwork.sol index c13d1cc1..574bbe3f 100644 --- a/contracts/SSVNetwork.sol +++ b/contracts/SSVNetwork.sol @@ -301,6 +301,12 @@ 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 @@ -405,9 +411,7 @@ contract SSVNetwork is OwnableUpgradeable, ISSVNetwork { return _ownerPodBalance(pod, _clusterCurrentIndex(clusterId)); } - function operatorSnapshot(uint64 operatorId) external view returns (Snapshot memory) { - return _getSnapshot(_operators[operatorId], uint64(block.number)); - } + /** * @dev Validates the params for a validator.