Final diff for Auction.sol
diff --git a/contracts/Auction.sol b/contracts/Auction.sol
index ae5fd02..fe74efc 100644
--- a/contracts/Auction.sol
+++ b/contracts/Auction.sol
@@ -13,7 +13,7 @@ import '@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.
contract Auction is IAuction, Initializable, AccessControlUpgradeable, PausableUpgradeable, ReentrancyGuardUpgradeable {
IStaderConfig public override staderConfig;
- uint256 public override nextLot;
+ uint96 public override nextLot;
uint256 public override bidIncrement;
uint256 public override duration;
@@ -47,15 +47,14 @@ contract Auction is IAuction, Initializable, AccessControlUpgradeable, PausableU
function createLot(uint256 _sdAmount) external override whenNotPaused {
lots[nextLot].startBlock = block.number;
- lots[nextLot].endBlock = block.number + duration;
+ uint256 _duration = duration;
+ lots[nextLot].endBlock = block.number + _duration;
lots[nextLot].sdAmount = _sdAmount;
- LotItem storage lotItem = lots[nextLot];
-
if (!IERC20(staderConfig.getStaderToken()).transferFrom(msg.sender, address(this), _sdAmount)) {
revert SDTransferFailed();
}
- emit LotCreated(nextLot, lotItem.sdAmount, lotItem.startBlock, lotItem.endBlock, bidIncrement);
+ emit LotCreated(nextLot, _sdAmount, block.number, block.number + _duration, bidIncrement);
nextLot++;
}
@@ -80,14 +79,16 @@ contract Auction is IAuction, Initializable, AccessControlUpgradeable, PausableU
function claimSD(uint256 lotId) external override {
LotItem storage lotItem = lots[lotId];
if (block.number <= lotItem.endBlock) revert AuctionNotEnded();
- if (msg.sender != lotItem.highestBidder) revert notQualified();
+ address _highestBidder = lotItem.highestBidder;
+ if (msg.sender != _highestBidder) revert notQualified();
if (lotItem.sdClaimed) revert AlreadyClaimed();
lotItem.sdClaimed = true;
- if (!IERC20(staderConfig.getStaderToken()).transfer(lotItem.highestBidder, lotItem.sdAmount)) {
+ uint256 _sdAmount = lotItem.sdAmount;
+ if (!IERC20(staderConfig.getStaderToken()).transfer(_highestBidder, _sdAmount)) {
revert SDTransferFailed();
}
- emit SDClaimed(lotId, lotItem.highestBidder, lotItem.sdAmount);
+ emit SDClaimed(lotId, _highestBidder, _sdAmount);
}
function transferHighestBidToSSPM(uint256 lotId) external override nonReentrant {
Final diff for IAuctionFinal.sol
diff --git a/contracts/interfaces/SDCollateral/IAuction.sol b/contracts/interfaces/SDCollateral/IAuction.sol
index 04d3164..ea95207 100644
--- a/contracts/interfaces/SDCollateral/IAuction.sol
+++ b/contracts/interfaces/SDCollateral/IAuction.sol
@@ -65,9 +65,10 @@ interface IAuction {
//getters
function staderConfig() external view returns (IStaderConfig);
- function nextLot() external view returns (uint256);
+ function nextLot() external view returns (uint96);
function bidIncrement() external view returns (uint256);
function duration() external view returns (uint256);
}
Final diff for NodeElRewardVault.sol
diff --git a/contracts/NodeELRewardVault.sol b/contracts/NodeELRewardVault.sol
index b10417a..2ae0d59 100644
--- a/contracts/NodeELRewardVault.sol
+++ b/contracts/NodeELRewardVault.sol
@@ -22,25 +22,46 @@ contract NodeELRewardVault is INodeELRewardVault {
}
function withdraw() external override {
- uint8 poolId = IVaultProxy(address(this)).poolId();
- uint256 operatorId = IVaultProxy(address(this)).id();
- IStaderConfig staderConfig = IVaultProxy(address(this)).staderConfig();
+ uint8 poolId;
+ uint256 operatorId;
+ IStaderConfig staderConfig;
+ assembly {
+ // function sigs for "poolId()", "id()", and "staderConfig()"
+ mstore(0x00, 0x490ffa35af640d0f3e0dc34e)
+ if iszero(staticcall(gas(), address(), 0x1c, 0x04, 0x20, 0x20)) {revert(0, 0)}
+ poolId := mload(0x20)
+ if iszero(staticcall(gas(), address(), 0x18, 0x04, 0x20, 0x20)) {revert(0, 0)}
+ operatorId := mload(0x20)
+ if iszero(staticcall(gas(), address(), 0x14, 0x04, 0x20, 0x20)) {revert(0, 0)}
+ staderConfig := mload(0x20)
+ }
uint256 totalRewards = address(this).balance;
if (totalRewards == 0) {
revert NotEnoughRewardToWithdraw();
}
- (uint256 userShare, uint256 operatorShare, uint256 protocolShare) = IPoolUtils(staderConfig.getPoolUtils())
- .calculateRewardShare(poolId, totalRewards);
+ IPoolUtils poolUtils = IPoolUtils(staderConfig.getPoolUtils());
+ (uint256 userShare, uint256 operatorShare, uint256 protocolShare) = poolUtils.calculateRewardShare(poolId, totalRewards);
// Distribute rewards
IStaderStakePoolManager(staderConfig.getStakePoolManager()).receiveExecutionLayerRewards{value: userShare}();
// slither-disable-next-line arbitrary-send-eth
UtilLib.sendValue(payable(staderConfig.getStaderTreasury()), protocolShare);
- address operator = UtilLib.getOperatorAddressByOperatorId(poolId, operatorId, staderConfig);
+ address operator = getOperatorAddressByOperatorId(poolId, operatorId, poolUtils);
IOperatorRewardsCollector(staderConfig.getOperatorRewardsCollector()).depositFor{value: operatorShare}(
operator
);
emit Withdrawal(protocolShare, operatorShare, userShare);
}
+
+ function getOperatorAddressByOperatorId(
+ uint8 _poolId,
+ uint256 _operatorId,
+ IPoolUtils poolUtils
+ ) internal view returns (address) {
+ address nodeRegistry = poolUtils.getNodeRegistry(_poolId);
+ (, , , , address operatorAddress) = INodeRegistry(nodeRegistry).operatorStructById(_operatorId);
+ return operatorAddress;
+ }
}
Final diff for OperatorRewardsCollector.sol
diff --git a/contracts/OperatorRewardsCollector.sol b/contracts/OperatorRewardsCollector.sol
index e80db8a..d284367 100644
--- a/contracts/OperatorRewardsCollector.sol
+++ b/contracts/OperatorRewardsCollector.sol
@@ -46,7 +46,7 @@ contract OperatorRewardsCollector is
function claim() external whenNotPaused {
address operator = msg.sender;
uint256 amount = balances[operator];
- balances[operator] -= amount;
+ balances[operator] = 0;
address operatorRewardsAddr = UtilLib.getOperatorRewardAddress(msg.sender, staderConfig);
UtilLib.sendValue(operatorRewardsAddr, amount);
Final diff for Penalty.sol
diff --git a/contracts/Penalty.sol b/contracts/Penalty.sol
index d6a28dc..9e0bfa6 100644
--- a/contracts/Penalty.sol
+++ b/contracts/Penalty.sol
@@ -98,13 +98,14 @@ contract Penalty is IPenalty, Initializable, AccessControlUpgradeable, Reentranc
function updateTotalPenaltyAmount(bytes[] calldata _pubkey) external override nonReentrant {
uint256 reportedValidatorCount = _pubkey.length;
for (uint256 i; i < reportedValidatorCount; ) {
- if (UtilLib.getValidatorSettleStatus(_pubkey[i], staderConfig)) {
+ IStaderConfig _staderConfig = staderConfig;
+ if (UtilLib.getValidatorSettleStatus(_pubkey[i], _staderConfig)) {
revert ValidatorSettled();
}
bytes32 pubkeyRoot = UtilLib.getPubkeyRoot(_pubkey[i]);
// Retrieve the penalty for changing the fee recipient address based on Rated.network data.
uint256 _mevTheftPenalty = calculateMEVTheftPenalty(pubkeyRoot);
- uint256 _missedAttestationPenalty = calculateMissedAttestationPenalty(pubkeyRoot);
+ uint256 _missedAttestationPenalty = _calculateMissedAttestationPenalty(_staderConfig, pubkeyRoot);
// Compute the total penalty for the given validator public key,
// taking into account additional penalties and penalty reversals from the DAO.
@@ -119,6 +120,12 @@ contract Penalty is IPenalty, Initializable, AccessControlUpgradeable, Reentranc
}
}
+ function _calculateMissedAttestationPenalty(IStaderConfig _staderConfig, bytes32 _pubkeyRoot) internal view returns (uint256) {
+ return
+ IStaderOracle(_staderConfig.getStaderOracle()).missedAttestationPenalty(_pubkeyRoot) *
+ missedAttestationPenaltyPerStrike;
+ }
+
/// @inheritdoc IPenalty
function calculateMEVTheftPenalty(bytes32 _pubkeyRoot) public override returns (uint256) {
// Retrieve the epochs in which the validator violated the fee recipient change rule.
@@ -130,9 +137,7 @@ contract Penalty is IPenalty, Initializable, AccessControlUpgradeable, Reentranc
/// @inheritdoc IPenalty
function calculateMissedAttestationPenalty(bytes32 _pubkeyRoot) public view override returns (uint256) {
- return
- IStaderOracle(staderConfig.getStaderOracle()).missedAttestationPenalty(_pubkeyRoot) *
- missedAttestationPenaltyPerStrike;
+ return _calculateMissedAttestationPenalty(staderConfig, _pubkeyRoot);
}
/// @inheritdoc IPenalty
Final diff for PermissionedNodeRegistry.sol
diff --git a/contracts/PermissionedNodeRegistry.sol b/contracts/PermissionedNodeRegistry.sol
index ca8aa81..bba1423 100644
--- a/contracts/PermissionedNodeRegistry.sol
+++ b/contracts/PermissionedNodeRegistry.sol
@@ -115,7 +115,8 @@ contract PermissionedNodeRegistry is
}
IPoolUtils(poolUtils).onlyValidName(_operatorName);
UtilLib.checkNonZeroAddress(_operatorRewardAddress);
- if (nextOperatorId > maxOperatorId) {
+ uint256 _nextOperatorId = nextOperatorId;
+ if (_nextOperatorId > maxOperatorId) {
revert MaxOperatorLimitReached();
}
if (!permissionList[msg.sender]) {
@@ -126,7 +127,7 @@ contract PermissionedNodeRegistry is
revert OperatorAlreadyOnBoardedInProtocol();
}
feeRecipientAddress = staderConfig.getPermissionedSocializingPool();
- onboardOperator(_operatorName, _operatorRewardAddress);
+ onboardOperator(_nextOperatorId, _operatorName, _operatorRewardAddress);
return feeRecipientAddress;
}
@@ -143,41 +144,47 @@ contract PermissionedNodeRegistry is
bytes[] calldata _depositSignature
) external override whenNotPaused {
uint256 operatorId = onlyActiveOperator(msg.sender);
+ IStaderConfig _staderConfig = staderConfig;
(uint256 keyCount, uint256 operatorTotalKeys) = checkInputKeysCountAndCollateral(
+ _staderConfig,
_pubkey.length,
_preDepositSignature.length,
_depositSignature.length,
operatorId
);
- address vaultFactory = staderConfig.getVaultFactory();
+ address vaultFactory = _staderConfig.getVaultFactory();
address poolUtils = staderConfig.getPoolUtils();
+ uint256 _nextValidatorId = nextValidatorId;
for (uint256 i; i < keyCount; ) {
IPoolUtils(poolUtils).onlyValidKeys(_pubkey[i], _preDepositSignature[i], _depositSignature[i]);
- address withdrawVault = IVaultFactory(vaultFactory).deployWithdrawVault(
- POOL_ID,
- operatorId,
- operatorTotalKeys + i, //operator totalKeys
- nextValidatorId
- );
- validatorRegistry[nextValidatorId] = Validator(
- ValidatorStatus.INITIALIZED,
- _pubkey[i],
- _preDepositSignature[i],
- _depositSignature[i],
- withdrawVault,
- operatorId,
- 0,
- 0
- );
- validatorIdByPubkey[_pubkey[i]] = nextValidatorId;
- validatorIdsByOperatorId[operatorId].push(nextValidatorId);
- emit AddedValidatorKey(msg.sender, _pubkey[i], nextValidatorId);
- nextValidatorId++;
+ { // @audit: used due to `stack too deep` errors
+ address withdrawVault = IVaultFactory(vaultFactory).deployWithdrawVault(
+ POOL_ID,
+ operatorId,
+ operatorTotalKeys + i, //operator totalKeys
+ _nextValidatorId
+ );
+ // @audit: stored seperately due to `stack too deep` errors
+ validatorRegistry[_nextValidatorId].status = ValidatorStatus.INITIALIZED;
+ validatorRegistry[_nextValidatorId].pubkey = _pubkey[i];
+ validatorRegistry[_nextValidatorId].preDepositSignature = _preDepositSignature[i];
+ validatorRegistry[_nextValidatorId].depositSignature = _depositSignature[i];
+ validatorRegistry[_nextValidatorId].operatorId = operatorId;
+ validatorRegistry[_nextValidatorId].withdrawVaultAddress = withdrawVault;
+ validatorRegistry[_nextValidatorId].depositBlock = 0;
+ validatorRegistry[_nextValidatorId].withdrawnBlock = 0;
+ }
+
+ validatorIdByPubkey[_pubkey[i]] = _nextValidatorId;
+ validatorIdsByOperatorId[operatorId].push(_nextValidatorId);
+ emit AddedValidatorKey(msg.sender, _pubkey[i], _nextValidatorId);
+ _nextValidatorId++;
unchecked {
++i;
}
}
+ nextValidatorId = _nextValidatorId;
}
/**
@@ -320,7 +327,7 @@ contract PermissionedNodeRegistry is
revert UNEXPECTED_STATUS();
}
validatorRegistry[validatorId].status = ValidatorStatus.WITHDRAWN;
- validatorRegistry[validatorId].withdrawnBlock = block.number;
+ validatorRegistry[validatorId].withdrawnBlock = uint48(block.number);
IValidatorWithdrawalVault(validatorRegistry[validatorId].withdrawVaultAddress).settleFunds();
emit ValidatorWithdrawn(_pubkeys[i], validatorId);
unchecked {
@@ -375,7 +382,7 @@ contract PermissionedNodeRegistry is
*/
function updateDepositStatusAndBlock(uint256 _validatorId) external override {
UtilLib.onlyStaderContract(msg.sender, staderConfig, staderConfig.PERMISSIONED_POOL());
- validatorRegistry[_validatorId].depositBlock = block.number;
+ validatorRegistry[_validatorId].depositBlock = uint48(block.number);
markValidatorDeposited(_validatorId);
emit UpdatedValidatorDepositBlock(_validatorId, block.number);
}
@@ -401,8 +408,7 @@ contract PermissionedNodeRegistry is
function updateOperatorDetails(string calldata _operatorName, address payable _rewardAddress) external override {
IPoolUtils(staderConfig.getPoolUtils()).onlyValidName(_operatorName);
UtilLib.checkNonZeroAddress(_rewardAddress);
- onlyActiveOperator(msg.sender);
- uint256 operatorId = operatorIDByAddress[msg.sender];
+ uint256 operatorId = onlyActiveOperator(msg.sender);
operatorStructById[operatorId].operatorName = _operatorName;
operatorStructById[operatorId].operatorRewardAddress = _rewardAddress;
emit UpdatedOperatorDetails(msg.sender, _operatorName, _rewardAddress);
@@ -658,8 +664,8 @@ contract PermissionedNodeRegistry is
onlyPreDepositValidator(validatorId);
}
- function onboardOperator(string calldata _operatorName, address payable _operatorRewardAddress) internal {
- operatorStructById[nextOperatorId] = Operator(true, true, _operatorName, _operatorRewardAddress, msg.sender);
+ function onboardOperator(uint256 _nextOperatorId, string calldata _operatorName, address payable _operatorRewardAddress) internal {
+ operatorStructById[_nextOperatorId] = Operator(true, true, _operatorName, _operatorRewardAddress, msg.sender);
operatorIDByAddress[msg.sender] = nextOperatorId;
socializingPoolStateChangeBlock[nextOperatorId] = block.number;
nextOperatorId++;
@@ -685,6 +691,7 @@ contract PermissionedNodeRegistry is
// validate the input of `addValidatorKeys` function
function checkInputKeysCountAndCollateral(
+ IStaderConfig _staderConfig,
uint256 _pubkeyLength,
uint256 _preDepositSignatureLength,
uint256 _depositSignatureLength,
@@ -706,7 +713,7 @@ contract PermissionedNodeRegistry is
//checks if operator has enough SD collateral for adding `keyCount` keys
//SD threshold for permissioned NOs is 0 for phase1
if (
- !ISDCollateral(staderConfig.getSDCollateral()).hasEnoughSDCollateral(
+ !ISDCollateral(_staderConfig.getSDCollateral()).hasEnoughSDCollateral(
msg.sender,
POOL_ID,
totalNonTerminalKeys + keyCount
Final diff for PermissionedPool.sol
diff --git a/contracts/PermissionedPool.sol b/contracts/PermissionedPool.sol
index 85ec85d..9c58bc4 100644
--- a/contracts/PermissionedPool.sol
+++ b/contracts/PermissionedPool.sol
@@ -23,10 +23,10 @@ contract PermissionedPool is IStaderPoolBase, Initializable, AccessControlUpgrad
IStaderConfig public staderConfig;
// @inheritdoc IStaderPoolBase
- uint256 public override protocolFee;
+ uint48 public override protocolFee;
// @inheritdoc IStaderPoolBase
- uint256 public override operatorFee;
+ uint48 public override operatorFee;
uint256 public preDepositValidatorCount;
@@ -97,6 +97,7 @@ contract PermissionedPool is IStaderPoolBase, Initializable, AccessControlUpgrad
// i is the operator Id
uint256 selectedOperatorCapacityLength = selectedOperatorCapacity.length;
+ IStaderConfig _staderConfig = staderConfig;
for (uint256 i = 1; i < selectedOperatorCapacityLength; ) {
uint256 validatorToDeposit = selectedOperatorCapacity[i];
if (validatorToDeposit == 0) {
@@ -112,7 +113,7 @@ contract PermissionedPool is IStaderPoolBase, Initializable, AccessControlUpgrad
index++
) {
uint256 validatorId = INodeRegistry(nodeRegistryAddress).validatorIdsByOperatorId(i, index);
- preDepositOnBeaconChain(nodeRegistryAddress, vaultFactory, ethDepositContract, validatorId);
+ preDepositOnBeaconChain(_staderConfig, nodeRegistryAddress, vaultFactory, ethDepositContract, validatorId);
}
IPermissionedNodeRegistry(nodeRegistryAddress).updateQueuedValidatorIndex(
i,
@@ -137,7 +138,7 @@ contract PermissionedPool is IStaderPoolBase, Initializable, AccessControlUpgrad
for (uint256 i; i < pubkeyCount; ) {
IPermissionedNodeRegistry(nodeRegistryAddress).onlyPreDepositValidator(_pubkey[i]);
uint256 validatorId = INodeRegistry(nodeRegistryAddress).validatorIdByPubkey(_pubkey[i]);
- (, , , bytes memory depositSignature, address withdrawVaultAddress, , , ) = INodeRegistry(
+ (, , , bytes memory depositSignature, , address withdrawVaultAddress, , ) = INodeRegistry(
nodeRegistryAddress
).validatorRegistry(validatorId);
bytes memory withdrawCredential = IVaultFactory(vaultFactory).getValidatorWithdrawCredential(
@@ -238,8 +239,8 @@ contract PermissionedPool is IStaderPoolBase, Initializable, AccessControlUpgrad
if (_protocolFee + _operatorFee > MAX_COMMISSION_LIMIT_BIPS) {
revert InvalidCommission();
}
- protocolFee = _protocolFee;
- operatorFee = _operatorFee;
+ protocolFee = uint48(_protocolFee);
+ operatorFee = uint48(_operatorFee);
emit UpdatedCommissionFees(_protocolFee, _operatorFee);
}
@@ -286,19 +287,20 @@ contract PermissionedPool is IStaderPoolBase, Initializable, AccessControlUpgrad
// deposit `PRE_DEPOSIT_SIZE` for validator
function preDepositOnBeaconChain(
+ IStaderConfig _staderConfig,
address _nodeRegistryAddress,
address _vaultFactory,
address _ethDepositContract,
uint256 _validatorId
) internal {
- (, bytes memory pubkey, bytes memory preDepositSignature, , address withdrawVaultAddress, , , ) = INodeRegistry(
+ (, bytes memory pubkey, bytes memory preDepositSignature, , , address withdrawVaultAddress, , ) = INodeRegistry(
_nodeRegistryAddress
).validatorRegistry(_validatorId);
bytes memory withdrawCredential = IVaultFactory(_vaultFactory).getValidatorWithdrawCredential(
withdrawVaultAddress
);
- uint256 preDepositSize = staderConfig.getPreDepositSize();
+ uint256 preDepositSize = _staderConfig.getPreDepositSize();
bytes32 depositDataRoot = this.computeDepositDataRoot(
pubkey,
preDepositSignature,
Final diff for PermissionlessNodeRegistry.sol
diff --git a/contracts/PermissionlessNodeRegistry.sol b/contracts/PermissionlessNodeRegistry.sol
index 9640556..536dee6 100644
--- a/contracts/PermissionlessNodeRegistry.sol
+++ b/contracts/PermissionlessNodeRegistry.sol
@@ -107,11 +107,12 @@ contract PermissionlessNodeRegistry is
POOL_ID,
nextOperatorId
);
- nodeELRewardVaultByOperatorId[nextOperatorId] = nodeELRewardVault;
+ uint256 _nextOperatorId = nextOperatorId;
+ nodeELRewardVaultByOperatorId[_nextOperatorId] = nodeELRewardVault;
feeRecipientAddress = _optInForSocializingPool
? staderConfig.getPermissionlessSocializingPool()
: nodeELRewardVault;
- onboardOperator(_optInForSocializingPool, _operatorName, _operatorRewardAddress);
+ onboardOperator(_nextOperatorId, _optInForSocializingPool, _operatorName, _operatorRewardAddress);
return feeRecipientAddress;
}
@@ -128,42 +129,47 @@ contract PermissionlessNodeRegistry is
bytes[] calldata _depositSignature
) external payable override nonReentrant whenNotPaused {
uint256 operatorId = onlyActiveOperator(msg.sender);
+ IStaderConfig _staderConfig = staderConfig;
(uint256 keyCount, uint256 operatorTotalKeys) = checkInputKeysCountAndCollateral(
+ _staderConfig,
_pubkey.length,
_preDepositSignature.length,
_depositSignature.length,
operatorId
);
- address vaultFactory = staderConfig.getVaultFactory();
+ address vaultFactory = _staderConfig.getVaultFactory();
address poolUtils = staderConfig.getPoolUtils();
+ uint256 _nextValidatorId = nextValidatorId;
for (uint256 i; i < keyCount; ) {
IPoolUtils(poolUtils).onlyValidKeys(_pubkey[i], _preDepositSignature[i], _depositSignature[i]);
- address withdrawVault = IVaultFactory(vaultFactory).deployWithdrawVault(
- POOL_ID,
- operatorId,
- operatorTotalKeys + i, //operator totalKeys
- nextValidatorId
- );
- validatorRegistry[nextValidatorId] = Validator(
- ValidatorStatus.INITIALIZED,
- _pubkey[i],
- _preDepositSignature[i],
- _depositSignature[i],
- withdrawVault,
- operatorId,
- 0,
- 0
- );
-
- validatorIdByPubkey[_pubkey[i]] = nextValidatorId;
- validatorIdsByOperatorId[operatorId].push(nextValidatorId);
- emit AddedValidatorKey(msg.sender, _pubkey[i], nextValidatorId);
- nextValidatorId++;
+ { // @audit: used due to `stack too deep` errors
+ address withdrawVault = IVaultFactory(vaultFactory).deployWithdrawVault(
+ POOL_ID,
+ operatorId,
+ operatorTotalKeys + i, //operator totalKeys
+ _nextValidatorId
+ );
+ // @audit: stored seperately due to `stack too deep` errors
+ validatorRegistry[_nextValidatorId].status = ValidatorStatus.INITIALIZED;
+ validatorRegistry[_nextValidatorId].pubkey = _pubkey[i];
+ validatorRegistry[_nextValidatorId].preDepositSignature = _preDepositSignature[i];
+ validatorRegistry[_nextValidatorId].depositSignature = _depositSignature[i];
+ validatorRegistry[_nextValidatorId].operatorId = operatorId;
+ validatorRegistry[_nextValidatorId].withdrawVaultAddress = withdrawVault;
+ validatorRegistry[_nextValidatorId].depositBlock = 0;
+ validatorRegistry[_nextValidatorId].withdrawnBlock = 0;
+ }
+
+ validatorIdByPubkey[_pubkey[i]] = _nextValidatorId;
+ validatorIdsByOperatorId[operatorId].push(_nextValidatorId);
+ emit AddedValidatorKey(msg.sender, _pubkey[i], _nextValidatorId);
+ _nextValidatorId++;
unchecked {
++i;
}
}
+ nextValidatorId = _nextValidatorId;
//slither-disable-next-line arbitrary-send-eth
IPermissionlessPool(staderConfig.getPermissionlessPool()).preDepositOnBeaconChain{
@@ -196,15 +202,19 @@ contract PermissionlessNodeRegistry is
revert TooManyVerifiedKeysReported();
}
+ uint256 _validatorQueueSize = validatorQueueSize;
for (uint256 i; i < readyToDepositValidatorsLength; ) {
uint256 validatorId = validatorIdByPubkey[_readyToDepositPubkey[i]];
onlyInitializedValidator(validatorId);
- markKeyReadyToDeposit(validatorId);
+ validatorRegistry[validatorId].status = ValidatorStatus.PRE_DEPOSIT;
+ queuedValidators[_validatorQueueSize] = validatorId;
+ _validatorQueueSize++;
emit ValidatorMarkedReadyToDeposit(_readyToDepositPubkey[i], validatorId);
unchecked {
++i;
}
}
+ validatorQueueSize = _validatorQueueSize;
if (frontRunValidatorsLength > 0) {
IStaderInsuranceFund(staderConfig.getStaderInsuranceFund()).depositFund{
@@ -250,7 +260,7 @@ contract PermissionlessNodeRegistry is
revert UNEXPECTED_STATUS();
}
validatorRegistry[validatorId].status = ValidatorStatus.WITHDRAWN;
- validatorRegistry[validatorId].withdrawnBlock = block.number;
+ validatorRegistry[validatorId].withdrawnBlock = uint48(block.number);
IValidatorWithdrawalVault(validatorRegistry[validatorId].withdrawVaultAddress).settleFunds();
emit ValidatorWithdrawn(_pubkeys[i], validatorId);
unchecked {
@@ -278,7 +288,7 @@ contract PermissionlessNodeRegistry is
*/
function updateDepositStatusAndBlock(uint256 _validatorId) external override {
UtilLib.onlyStaderContract(msg.sender, staderConfig, staderConfig.PERMISSIONLESS_POOL());
- validatorRegistry[_validatorId].depositBlock = block.number;
+ validatorRegistry[_validatorId].depositBlock = uint48(block.number);
markValidatorDeposited(_validatorId);
emit UpdatedValidatorDepositBlock(_validatorId, block.number);
}
@@ -366,8 +376,7 @@ contract PermissionlessNodeRegistry is
function updateOperatorDetails(string calldata _operatorName, address payable _rewardAddress) external override {
IPoolUtils(staderConfig.getPoolUtils()).onlyValidName(_operatorName);
UtilLib.checkNonZeroAddress(_rewardAddress);
- onlyActiveOperator(msg.sender);
- uint256 operatorId = operatorIDByAddress[msg.sender];
+ uint256 operatorId = onlyActiveOperator(msg.sender);
operatorStructById[operatorId].operatorName = _operatorName;
operatorStructById[operatorId].operatorRewardAddress = _rewardAddress;
emit UpdatedOperatorDetails(msg.sender, _operatorName, _rewardAddress);
@@ -596,11 +605,12 @@ contract PermissionlessNodeRegistry is
}
function onboardOperator(
+ uint256 _nextOperatorId,
bool _optInForSocializingPool,
string calldata _operatorName,
address payable _operatorRewardAddress
) internal {
- operatorStructById[nextOperatorId] = Operator(
+ operatorStructById[_nextOperatorId] = Operator(
true,
_optInForSocializingPool,
_operatorName,
@@ -614,13 +624,6 @@ contract PermissionlessNodeRegistry is
emit OnboardedOperator(msg.sender, _operatorRewardAddress, nextOperatorId - 1, _optInForSocializingPool);
}
- // mark validator `PRE_DEPOSIT` after successful key verification and front run check
- function markKeyReadyToDeposit(uint256 _validatorId) internal {
- validatorRegistry[_validatorId].status = ValidatorStatus.PRE_DEPOSIT;
- queuedValidators[validatorQueueSize] = _validatorId;
- validatorQueueSize++;
- }
-
// handle front run validator by changing their status, deactivating operator and imposing penalty
function handleFrontRun(uint256 _validatorId) internal {
validatorRegistry[_validatorId].status = ValidatorStatus.FRONT_RUN;
@@ -641,6 +644,7 @@ contract PermissionlessNodeRegistry is
// validate the input of `addValidatorKeys` function
function checkInputKeysCountAndCollateral(
+ IStaderConfig _staderConfig,
uint256 _pubkeyLength,
uint256 _preDepositSignatureLength,
uint256 _depositSignatureLength,
@@ -666,7 +670,7 @@ contract PermissionlessNodeRegistry is
}
//checks if operator has enough SD collateral for adding `keyCount` keys
if (
- !ISDCollateral(staderConfig.getSDCollateral()).hasEnoughSDCollateral(
+ !ISDCollateral(_staderConfig.getSDCollateral()).hasEnoughSDCollateral(
msg.sender,
POOL_ID,
totalNonTerminalKeys + keyCount
Final diff for PermissionlessPool.sol
diff --git a/contracts/PermissionlessPool.sol b/contracts/PermissionlessPool.sol
index 046761d..797e213 100644
--- a/contracts/PermissionlessPool.sol
+++ b/contracts/PermissionlessPool.sol
@@ -23,10 +23,10 @@ contract PermissionlessPool is IStaderPoolBase, Initializable, AccessControlUpgr
uint256 public constant DEPOSIT_NODE_BOND = 3 ether;
/// @inheritdoc IStaderPoolBase
- uint256 public override protocolFee;
+ uint48 public override protocolFee;
/// @inheritdoc IStaderPoolBase
- uint256 public override operatorFee;
+ uint48 public override operatorFee;
uint256 public constant MAX_COMMISSION_LIMIT_BIPS = 1500;
@@ -68,8 +68,8 @@ contract PermissionlessPool is IStaderPoolBase, Initializable, AccessControlUpgr
if (_protocolFee + _operatorFee > MAX_COMMISSION_LIMIT_BIPS) {
revert InvalidCommission();
}
- protocolFee = _protocolFee;
- operatorFee = _operatorFee;
+ protocolFee = uint48(_protocolFee);
+ operatorFee = uint48(_operatorFee);
emit UpdatedCommissionFees(_protocolFee, _operatorFee);
}
@@ -245,7 +245,7 @@ contract PermissionlessPool is IStaderPoolBase, Initializable, AccessControlUpgr
uint256 _validatorId,
uint256 _DEPOSIT_SIZE
) internal {
- (, bytes memory pubkey, , bytes memory depositSignature, address withdrawVaultAddress, , , ) = INodeRegistry(
+ (, bytes memory pubkey, , bytes memory depositSignature, , address withdrawVaultAddress, , ) = INodeRegistry(
_nodeRegistryAddress
).validatorRegistry(_validatorId);
Final diff for INodeRegistry.sol
diff --git a/contracts/interfaces/INodeRegistry.sol b/contracts/interfaces/INodeRegistry.sol
index 5360913..182ab42 100644
--- a/contracts/interfaces/INodeRegistry.sol
+++ b/contracts/interfaces/INodeRegistry.sol
@@ -8,10 +8,10 @@ struct Validator {
bytes pubkey; //pubkey of the validator
bytes preDepositSignature; //signature for 1 ETH deposit on beacon chain
bytes depositSignature; //signature for 31 ETH deposit on beacon chain
- address withdrawVaultAddress; //withdrawal vault address of validator
uint256 operatorId; // stader network assigned Id
- uint256 depositBlock; // block number of the 31ETH deposit
- uint256 withdrawnBlock; //block number when oracle report validator as withdrawn
+ address withdrawVaultAddress; //withdrawal vault address of validator
+ uint48 depositBlock; // block number of the 31ETH deposit
+ uint48 withdrawnBlock; //block number when oracle report validator as withdrawn
}
struct Operator {
@@ -72,10 +72,10 @@ interface INodeRegistry {
bytes calldata pubkey,
bytes calldata preDepositSignature,
bytes calldata depositSignature,
- address withdrawVaultAddress,
uint256 operatorId,
- uint256 depositTime,
- uint256 withdrawnTime
+ address withdrawVaultAddress,
+ uint48 depositTime,
+ uint48 withdrawnTime
);
Final diff for SDCollateral.sol
diff --git a/contracts/SDCollateral.sol b/contracts/SDCollateral.sol
index 0b5e22b..56c9c62 100644
--- a/contracts/SDCollateral.sol
+++ b/contracts/SDCollateral.sol
@@ -58,14 +58,15 @@ contract SDCollateral is ISDCollateral, Initializable, AccessControlUpgradeable,
function withdraw(uint256 _requestedSD) external override {
address operator = msg.sender;
uint256 opSDBalance = operatorSDBalance[operator];
-
- if (opSDBalance < getOperatorWithdrawThreshold(operator) + _requestedSD) {
+
+ IStaderConfig _staderConfig = staderConfig;
+ if (opSDBalance < _getOperatorWithdrawThreshold(_staderConfig, operator) + _requestedSD) {
revert InsufficientSDToWithdraw(opSDBalance);
}
- operatorSDBalance[operator] -= _requestedSD;
+ operatorSDBalance[operator] = opSDBalance - _requestedSD;
// cannot use safeERC20 as this contract is an upgradeable contract
- if (!IERC20(staderConfig.getStaderToken()).transfer(payable(operator), _requestedSD)) {
+ if (!IERC20(_staderConfig.getStaderToken()).transfer(payable(operator), _requestedSD)) {
revert SDTransferFailed();
}
@@ -76,26 +77,27 @@ contract SDCollateral is ISDCollateral, Initializable, AccessControlUpgradeable,
/// @dev callable only by respective withdrawVaults
/// @param _validatorId validator SD collateral to slash
function slashValidatorSD(uint256 _validatorId, uint8 _poolId) external override nonReentrant {
- address operator = UtilLib.getOperatorForValidSender(_poolId, _validatorId, msg.sender, staderConfig);
- isPoolThresholdValid(_poolId);
+ IStaderConfig _staderConfig = staderConfig;
+ address operator = UtilLib.getOperatorForValidSender(_poolId, _validatorId, msg.sender, _staderConfig);
PoolThresholdInfo storage poolThreshold = poolThresholdbyPoolId[_poolId];
- uint256 sdToSlash = convertETHToSD(poolThreshold.minThreshold);
- slashSD(operator, sdToSlash);
+ isPoolThresholdValid(poolThreshold);
+ uint256 sdToSlash = _convertETHToSD(_staderConfig, poolThreshold.minThreshold);
+ slashSD(_staderConfig, operator, sdToSlash);
}
/// @notice used to slash operator SD, incase of operator default
/// @dev do provide SD approval to auction contract using `maxApproveSD()`
/// @param _operator which operator SD collateral to slash
/// @param _sdToSlash amount of SD to slash
- function slashSD(address _operator, uint256 _sdToSlash) internal {
+ function slashSD(IStaderConfig _staderConfig, address _operator, uint256 _sdToSlash) internal {
uint256 sdBalance = operatorSDBalance[_operator];
uint256 sdSlashed = Math.min(_sdToSlash, sdBalance);
if (sdSlashed == 0) {
return;
}
- operatorSDBalance[_operator] -= sdSlashed;
- IAuction(staderConfig.getAuctionContract()).createLot(sdSlashed);
- emit SDSlashed(_operator, staderConfig.getAuctionContract(), sdSlashed);
+ operatorSDBalance[_operator] = sdBalance - sdSlashed;
+ IAuction(_staderConfig.getAuctionContract()).createLot(sdSlashed);
+ emit SDSlashed(_operator, _staderConfig.getAuctionContract(), sdSlashed);
}
/// @notice for max approval to auction contract for spending SD tokens
@@ -142,10 +144,14 @@ contract SDCollateral is ISDCollateral, Initializable, AccessControlUpgradeable,
// returns sum of withdraw threshold accounting for all its(op's) validators
function getOperatorWithdrawThreshold(address _operator) public view returns (uint256 operatorWithdrawThreshold) {
- (uint8 poolId, , uint256 validatorCount) = getOperatorInfo(_operator);
- isPoolThresholdValid(poolId);
+ return _getOperatorWithdrawThreshold(staderConfig, _operator);
+ }
+
+ function _getOperatorWithdrawThreshold(IStaderConfig _staderConfig, address _operator) internal view returns (uint256 operatorWithdrawThreshold) {
+ (uint8 poolId, , uint256 validatorCount) = getOperatorInfo(_staderConfig, _operator);
PoolThresholdInfo storage poolThreshold = poolThresholdbyPoolId[poolId];
- return convertETHToSD(poolThreshold.withdrawThreshold * validatorCount);
+ isPoolThresholdValid(poolThreshold);
+ return _convertETHToSD(_staderConfig, poolThreshold.withdrawThreshold * validatorCount);
}
/// @notice checks if operator has enough SD collateral to onboard validators in a specific pool
@@ -169,8 +175,8 @@ contract SDCollateral is ISDCollateral, Initializable, AccessControlUpgradeable,
override
returns (uint256 _minSDToBond)
{
- isPoolThresholdValid(_poolId);
PoolThresholdInfo storage poolThreshold = poolThresholdbyPoolId[_poolId];
+ isPoolThresholdValid(poolThreshold);
_minSDToBond = convertETHToSD(poolThreshold.minThreshold);
_minSDToBond *= _numValidator;
@@ -191,10 +197,10 @@ contract SDCollateral is ISDCollateral, Initializable, AccessControlUpgradeable,
}
function getRewardEligibleSD(address _operator) external view override returns (uint256 _rewardEligibleSD) {
- (uint8 poolId, , uint256 validatorCount) = getOperatorInfo(_operator);
+ (uint8 poolId, , uint256 validatorCount) = getOperatorInfo(staderConfig, _operator);
- isPoolThresholdValid(poolId);
PoolThresholdInfo storage poolThreshold = poolThresholdbyPoolId[poolId];
+ isPoolThresholdValid(poolThreshold);
uint256 totalMinThreshold = validatorCount * convertETHToSD(poolThreshold.minThreshold);
uint256 totalMaxThreshold = validatorCount * convertETHToSD(poolThreshold.maxThreshold);
@@ -208,13 +214,17 @@ contract SDCollateral is ISDCollateral, Initializable, AccessControlUpgradeable,
}
function convertETHToSD(uint256 _ethAmount) public view override returns (uint256) {
- uint256 sdPriceInETH = IStaderOracle(staderConfig.getStaderOracle()).getSDPriceInETH();
- return (_ethAmount * staderConfig.getDecimals()) / sdPriceInETH;
+ return _convertETHToSD(staderConfig, _ethAmount);
+ }
+
+ function _convertETHToSD(IStaderConfig _staderConfig, uint256 _ethAmount) internal view returns (uint256) {
+ uint256 sdPriceInETH = IStaderOracle(_staderConfig.getStaderOracle()).getSDPriceInETH();
+ return (_ethAmount * _staderConfig.getDecimals()) / sdPriceInETH;
}
// HELPER
- function getOperatorInfo(address _operator)
+ function getOperatorInfo(IStaderConfig _staderConfig, address _operator)
internal
view
returns (
@@ -223,7 +233,7 @@ contract SDCollateral is ISDCollateral, Initializable, AccessControlUpgradeable,
uint256 _validatorCount
)
{
- IPoolUtils poolUtils = IPoolUtils(staderConfig.getPoolUtils());
+ IPoolUtils poolUtils = IPoolUtils(_staderConfig.getPoolUtils());
_poolId = poolUtils.getOperatorPoolId(_operator);
INodeRegistry nodeRegistry = INodeRegistry(poolUtils.getNodeRegistry(_poolId));
_operatorId = nodeRegistry.operatorIDByAddress(_operator);
@@ -235,8 +245,8 @@ contract SDCollateral is ISDCollateral, Initializable, AccessControlUpgradeable,
);
}
- function isPoolThresholdValid(uint8 _poolId) internal view {
- if (bytes(poolThresholdbyPoolId[_poolId].units).length == 0) {
+ function isPoolThresholdValid(PoolThresholdInfo storage poolThreshold) internal view {
+ if (bytes(poolThreshold.units).length == 0) {
revert InvalidPoolId();
}
}
Final diff for SocializingPool.sol
diff --git a/contracts/SocializingPool.sol b/contracts/SocializingPool.sol
index 19d8cb2..42d3cad 100644
--- a/contracts/SocializingPool.sol
+++ b/contracts/SocializingPool.sol
@@ -21,15 +21,20 @@ contract SocializingPool is
PausableUpgradeable,
ReentrancyGuardUpgradeable
{
+ RewardsData public lastReportedRewardsData;
IStaderConfig public override staderConfig;
uint256 public override totalOperatorETHRewardsRemaining;
uint256 public override totalOperatorSDRewardsRemaining;
uint256 public override initialBlock;
+ struct RewardsInfo {
+ RewardsData rewardsDataMap;
+ bool handledRewards;
+ }
+
+ mapping(uint256 => RewardsInfo) rewardsInfo;
+
mapping(address => mapping(uint256 => bool)) public override claimedRewards;
- mapping(uint256 => bool) public handledRewards;
- RewardsData public lastReportedRewardsData;
- mapping(uint256 => RewardsData) public rewardsDataMap;
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
@@ -60,29 +65,32 @@ contract SocializingPool is
function handleRewards(RewardsData calldata _rewardsData) external override nonReentrant {
UtilLib.onlyStaderContract(msg.sender, staderConfig, staderConfig.STADER_ORACLE());
-
- if (handledRewards[_rewardsData.index]) {
+
+ RewardsInfo storage _rewardsInfo = rewardsInfo[_rewardsData.index];
+ if (_rewardsInfo.handledRewards) {
revert RewardAlreadyHandled();
}
+ uint256 _totalOperatorETHRewardsRemaining = totalOperatorSDRewardsRemaining;
if (
_rewardsData.operatorETHRewards + _rewardsData.userETHRewards + _rewardsData.protocolETHRewards >
- address(this).balance - totalOperatorETHRewardsRemaining
+ address(this).balance - _totalOperatorETHRewardsRemaining
) {
revert InsufficientETHRewards();
}
+ uint256 _totalOperatorSDRewardsRemaining = totalOperatorSDRewardsRemaining;
if (
_rewardsData.operatorSDRewards >
- IERC20(staderConfig.getStaderToken()).balanceOf(address(this)) - totalOperatorSDRewardsRemaining
+ IERC20(staderConfig.getStaderToken()).balanceOf(address(this)) - _totalOperatorSDRewardsRemaining
) {
revert InsufficientSDRewards();
}
- handledRewards[_rewardsData.index] = true;
- totalOperatorETHRewardsRemaining += _rewardsData.operatorETHRewards;
- totalOperatorSDRewardsRemaining += _rewardsData.operatorSDRewards;
+ _rewardsInfo.handledRewards = true;
+ totalOperatorETHRewardsRemaining = _totalOperatorETHRewardsRemaining + _rewardsData.operatorETHRewards;
+ totalOperatorSDRewardsRemaining = _totalOperatorSDRewardsRemaining + _rewardsData.operatorSDRewards;
lastReportedRewardsData = _rewardsData;
- rewardsDataMap[_rewardsData.index] = _rewardsData;
+ _rewardsInfo.rewardsDataMap = _rewardsData;
IStaderStakePoolManager(staderConfig.getStakePoolManager()).receiveExecutionLayerRewards{
value: _rewardsData.userETHRewards
@@ -110,10 +118,9 @@ contract SocializingPool is
uint256[] calldata _amountETH,
bytes32[][] calldata _merkleProof
) external override nonReentrant whenNotPaused {
- address operator = msg.sender;
- (uint256 totalAmountSD, uint256 totalAmountETH) = _claim(_index, operator, _amountSD, _amountETH, _merkleProof);
+ (uint256 totalAmountSD, uint256 totalAmountETH) = _claim(_index, _amountSD, _amountETH, _merkleProof);
- address operatorRewardsAddr = UtilLib.getOperatorRewardAddress(operator, staderConfig);
+ address operatorRewardsAddr = UtilLib.getOperatorRewardAddress(msg.sender, staderConfig);
bool success;
if (totalAmountETH > 0) {
@@ -136,45 +143,54 @@ contract SocializingPool is
function _claim(
uint256[] calldata _index,
- address _operator,
uint256[] calldata _amountSD,
uint256[] calldata _amountETH,
bytes32[][] calldata _merkleProof
) internal returns (uint256 _totalAmountSD, uint256 _totalAmountETH) {
uint256 indexLength = _index.length;
+ mapping(uint256 => bool) storage _claimedRewards = claimedRewards[msg.sender];
for (uint256 i = 0; i < indexLength; i++) {
if (_amountSD[i] == 0 && _amountETH[i] == 0) {
revert InvalidAmount();
}
- if (claimedRewards[_operator][_index[i]]) {
- revert RewardAlreadyClaimed(_operator, _index[i]);
+ if (_claimedRewards[_index[i]]) {
+ revert RewardAlreadyClaimed(msg.sender, _index[i]);
}
_totalAmountSD += _amountSD[i];
_totalAmountETH += _amountETH[i];
- claimedRewards[_operator][_index[i]] = true;
+ _claimedRewards[_index[i]] = true;
- if (!verifyProof(_index[i], _operator, _amountSD[i], _amountETH[i], _merkleProof[i])) {
- revert InvalidProof(_index[i], _operator);
+ if (!_verifyProof(_index[i], _amountSD[i], _amountETH[i], _merkleProof[i])) {
+ revert InvalidProof(_index[i], msg.sender);
}
}
}
- function verifyProof(
+ function _verifyProof(
uint256 _index,
- address _operator,
uint256 _amountSD,
uint256 _amountETH,
bytes32[] calldata _merkleProof
- ) public view returns (bool) {
+ ) internal view returns (bool) {
if (_index == 0 || _index > lastReportedRewardsData.index) {
revert InvalidCycleIndex();
}
- bytes32 merkleRoot = rewardsDataMap[_index].merkleRoot;
- bytes32 node = keccak256(abi.encodePacked(_operator, _amountSD, _amountETH));
+ bytes32 merkleRoot = rewardsInfo[_index].rewardsDataMap.merkleRoot;
+ bytes32 node = keccak256(abi.encodePacked(msg.sender, _amountSD, _amountETH));
return MerkleProofUpgradeable.verify(_merkleProof, merkleRoot, node);
}
+ function verifyProof(
+ uint256 _index,
+ address _operator,
+ uint256 _amountSD,
+ uint256 _amountETH,
+ bytes32[] calldata _merkleProof
+ ) public view returns (bool) {
+ return _verifyProof(_index, _amountSD, _amountETH, _merkleProof);
+ }
+
// SETTERS
function updateStaderConfig(address _staderConfig) external override onlyRole(DEFAULT_ADMIN_ROLE) {
UtilLib.checkNonZeroAddress(_staderConfig);
@@ -214,15 +230,16 @@ contract SocializingPool is
}
// for past cycles
- _startBlock = rewardsDataMap[_index - 1].reportingBlockNumber + 1;
- _endBlock = rewardsDataMap[_index].reportingBlockNumber;
+ _startBlock = rewardsInfo[_index - 1].rewardsDataMap.reportingBlockNumber + 1;
+ _endBlock = rewardsInfo[_index].rewardsDataMap.reportingBlockNumber;
// for current cycle
- if (rewardsDataMap[_index].reportingBlockNumber == 0) {
- if (rewardsDataMap[_index - 1].reportingBlockNumber == 0) {
+ if (rewardsInfo[_index].rewardsDataMap.reportingBlockNumber == 0) {
+ if (rewardsInfo[_index - 1].rewardsDataMap.reportingBlockNumber == 0) {
revert FutureCycleIndex();
}
- _endBlock = rewardsDataMap[_index - 1].reportingBlockNumber + cycleDuration;
+ _endBlock = rewardsInfo[_index - 1].rewardsDataMap.reportingBlockNumber + cycleDuration;
}
}
}
Final diff for StaderOracle.sol
diff --git a/contracts/StaderOracle.sol b/contracts/StaderOracle.sol
index ba007c5..7078a04 100644
--- a/contracts/StaderOracle.sol
+++ b/contracts/StaderOracle.sol
@@ -17,10 +17,10 @@ import '@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.
contract StaderOracle is IStaderOracle, AccessControlUpgradeable, PausableUpgradeable, ReentrancyGuardUpgradeable {
bool public override erInspectionMode;
bool public override isPORFeedBasedERData;
- SDPriceData public lastReportedSDPriceData;
+ uint40 public override erInspectionModeStartBlock;
IStaderConfig public override staderConfig;
- ExchangeRate public inspectionModeExchangeRate;
ExchangeRate public exchangeRate;
+ SDPriceData public lastReportedSDPriceData;
ValidatorStats public validatorStats;
uint256 public constant MAX_ER_UPDATE_FREQUENCY = 7200 * 7; // 7 days
@@ -29,16 +29,13 @@ contract StaderOracle is IStaderOracle, AccessControlUpgradeable, PausableUpgrad
uint256 public constant MIN_TRUSTED_NODES = 5;
/// @inheritdoc IStaderOracle
- uint256 public override reportingBlockNumberForWithdrawnValidators;
+ bool public override safeMode;
+ uint208 public override reportingBlockNumberForWithdrawnValidators;
+ ExchangeRate public inspectionModeExchangeRate;
/// @inheritdoc IStaderOracle
uint256 public override trustedNodesCount;
/// @inheritdoc IStaderOracle
uint256 public override lastReportedMAPDIndex;
- uint256 public override erInspectionModeStartBlock;
-
- // indicate the health of protocol on beacon chain
- // enabled by `MANAGER` if heavy slashing on protocol on beacon chain
- bool public override safeMode;
/// @inheritdoc IStaderOracle
mapping(address => bool) public override isTrustedNode;
@@ -432,7 +429,7 @@ contract StaderOracle is IStaderOracle, AccessControlUpgradeable, PausableUpgrad
submissionCount == trustedNodesCount / 2 + 1 &&
_withdrawnValidators.reportingBlockNumber > reportingBlockNumberForWithdrawnValidators
) {
- reportingBlockNumberForWithdrawnValidators = _withdrawnValidators.reportingBlockNumber;
+ reportingBlockNumberForWithdrawnValidators = uint208(_withdrawnValidators.reportingBlockNumber);
INodeRegistry(_withdrawnValidators.nodeRegistry).withdrawnValidators(_withdrawnValidators.sortedPubkeys);
// Emit withdrawn validators updated event
@@ -626,8 +623,9 @@ contract StaderOracle is IStaderOracle, AccessControlUpgradeable, PausableUpgrad
revert DuplicateSubmissionFromNode();
}
nodeSubmissionKeys[_nodeSubmissionKey] = true;
- submissionCountKeys[_submissionCountKey]++;
- _submissionCount = submissionCountKeys[_submissionCountKey];
+ uint8 submissionCountKeyUpdated = submissionCountKeys[_submissionCountKey] + 1;
+ submissionCountKeys[_submissionCountKey] = submissionCountKeyUpdated;
+ _submissionCount = submissionCountKeyUpdated;
}
function getSDPriceInETH() external view override returns (uint256) {
@@ -666,10 +664,10 @@ contract StaderOracle is IStaderOracle, AccessControlUpgradeable, PausableUpgrad
newExchangeRate <= ((currentExchangeRate * (ER_CHANGE_MAX_BPS + erChangeLimit)) / ER_CHANGE_MAX_BPS))
) {
erInspectionMode = true;
- erInspectionModeStartBlock = block.number;
+ erInspectionModeStartBlock = uint40(block.number);
inspectionModeExchangeRate.totalETHBalance = _newTotalETHBalance;
inspectionModeExchangeRate.totalETHXSupply = _newTotalETHXSupply;
- inspectionModeExchangeRate.reportingBlockNumber = _reportingBlockNumber;
+ inspectionModeExchangeRate.reportingBlockNumber = uint40(_reportingBlockNumber);
emit ERInspectionModeActivated(erInspectionMode, block.timestamp);
return;
}
@@ -683,7 +681,7 @@ contract StaderOracle is IStaderOracle, AccessControlUpgradeable, PausableUpgrad
) internal {
exchangeRate.totalETHBalance = _totalETHBalance;
exchangeRate.totalETHXSupply = _totalETHXSupply;
- exchangeRate.reportingBlockNumber = _reportingBlockNumber;
+ exchangeRate.reportingBlockNumber = uint40(_reportingBlockNumber);
// Emit balances updated event
emit ExchangeRateUpdated(
Final diff for StaderStakePoolsManager.sol
diff --git a/contracts/StaderStakePoolsManager.sol b/contracts/StaderStakePoolsManager.sol
index c4bb7d5..9ebddd5 100644
--- a/contracts/StaderStakePoolsManager.sol
+++ b/contracts/StaderStakePoolsManager.sol
@@ -35,8 +35,8 @@ contract StaderStakePoolsManager is
using Math for uint256;
using SafeMath for uint256;
IStaderConfig public staderConfig;
- uint256 public lastExcessETHDepositBlock;
- uint256 public excessETHDepositCoolDown;
+ uint48 public lastExcessETHDepositBlock;
+ uint48 public excessETHDepositCoolDown;
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
@@ -53,7 +53,7 @@ contract StaderStakePoolsManager is
__AccessControl_init();
__Pausable_init();
__ReentrancyGuard_init();
- lastExcessETHDepositBlock = block.number;
+ lastExcessETHDepositBlock = uint48(block.number);
excessETHDepositCoolDown = 3 * 7200;
staderConfig = IStaderConfig(_staderConfig);
_grantRole(DEFAULT_ADMIN_ROLE, _admin);
@@ -108,7 +108,7 @@ contract StaderStakePoolsManager is
function updateExcessETHDepositCoolDown(uint256 _excessETHDepositCoolDown) external {
UtilLib.onlyManagerRole(msg.sender, staderConfig);
- excessETHDepositCoolDown = _excessETHDepositCoolDown;
+ excessETHDepositCoolDown = uint48(_excessETHDepositCoolDown);
emit UpdatedExcessETHDepositCoolDown(_excessETHDepositCoolDown);
}
@@ -238,7 +238,7 @@ contract StaderStakePoolsManager is
uint256 poolDepositSize = staderConfig.getStakedEthPerNode() -
IPoolUtils(poolUtils).getCollateralETH(poolIdArray[i]);
- lastExcessETHDepositBlock = block.number;
+ lastExcessETHDepositBlock = uint48(block.number);
//slither-disable-next-line arbitrary-send-eth
IStaderPoolBase(poolAddress).stakeUserETHToBeaconChain{value: validatorToDeposit * poolDepositSize}();
emit ETHTransferredToPool(i, poolAddress, validatorToDeposit * poolDepositSize);
Final diff for ISocializingPool.sol
diff --git a/contracts/interfaces/ISocializingPool.sol b/contracts/interfaces/ISocializingPool.sol
index aceee8b..ab49093 100644
--- a/contracts/interfaces/ISocializingPool.sol
+++ b/contracts/interfaces/ISocializingPool.sol
@@ -7,14 +7,10 @@ import './IStaderConfig.sol';
/// @title RewardsData
/// @notice This struct holds rewards merkleRoot and rewards split
struct RewardsData {
- /// @notice The block number when the rewards data was last updated
- uint256 reportingBlockNumber;
/// @notice The index of merkle tree or rewards cycle
uint256 index;
/// @notice The merkle root hash
bytes32 merkleRoot;
- /// @notice pool id of operators
- uint8 poolId;
/// @notice operator ETH rewards for index cycle
uint256 operatorETHRewards;
/// @notice user ETH rewards for index cycle
@@ -23,6 +19,10 @@ struct RewardsData {
uint256 protocolETHRewards;
/// @notice operator SD rewards for index cycle
uint256 operatorSDRewards;
+ /// @notice pool id of operators
+ uint8 poolId;
+ /// @notice The block number when the rewards data was last updated
+ uint48 reportingBlockNumber;
}
Final diff for IStaderOracle.sol
diff --git a/contracts/interfaces/IStaderOracle.sol b/contracts/interfaces/IStaderOracle.sol
index d514c32..6f68195 100644
--- a/contracts/interfaces/IStaderOracle.sol
+++ b/contracts/interfaces/IStaderOracle.sol
@@ -31,7 +31,7 @@ struct MissedAttestationReportInfo {
/// @notice This struct holds data related to the exchange rate between ETH and ETHX.
struct ExchangeRate {
/// @notice The block number when the exchange rate was last updated.
- uint256 reportingBlockNumber;
+ uint40 reportingBlockNumber;
/// @notice The total balance of Ether (ETH) in the system.
uint256 totalETHBalance;
/// @notice The total supply of the liquid staking token (ETHX) in the system.
@@ -247,7 +247,7 @@ interface IStaderOracle {
function erChangeLimit() external view returns (uint256);
- function reportingBlockNumberForWithdrawnValidators() external view returns (uint256);
+ function reportingBlockNumberForWithdrawnValidators() external view returns (uint208);
// returns the count of trusted nodes
function trustedNodesCount() external view returns (uint256);
@@ -255,7 +255,7 @@ interface IStaderOracle {
//returns the latest consensus index for missed attestation penalty data report
function lastReportedMAPDIndex() external view returns (uint256);
- function erInspectionModeStartBlock() external view returns (uint256);
+ function erInspectionModeStartBlock() external view returns (uint40);
function safeMode() external view returns (bool);
Final diff for IStaderPoolBase.sol
diff --git a/contracts/interfaces/IStaderPoolBase.sol b/contracts/interfaces/IStaderPoolBase.sol
index f0fdcc0..57ae0f4 100644
--- a/contracts/interfaces/IStaderPoolBase.sol
+++ b/contracts/interfaces/IStaderPoolBase.sol
@@ -24,9 +24,9 @@ interface IStaderPoolBase {
//Getters
- function protocolFee() external view returns (uint256); // returns the protocol fee
+ function protocolFee() external view returns (uint48); // returns the protocol fee
- function operatorFee() external view returns (uint256); // returns the operator fee
+ function operatorFee() external view returns (uint48); // returns the operator fee
function getTotalActiveValidatorCount() external view returns (uint256); // returns the total number of active validators across all operators
Final diff for UserWithdrawalManager.sol
diff --git a/contracts/UserWithdrawalManager.sol b/contracts/UserWithdrawalManager.sol
index f563434..eb346e1 100644
--- a/contracts/UserWithdrawalManager.sol
+++ b/contracts/UserWithdrawalManager.sol
@@ -40,10 +40,10 @@ contract UserWithdrawalManager is
/// @notice structure representing a user request for withdrawal.
struct UserWithdrawInfo {
address payable owner; // address that can claim eth on behalf of this request
+ uint96 requestBlock; // block number of withdraw request
uint256 ethXAmount; //amount of ethX share locked for withdrawal
uint256 ethExpected; //eth requested according to given share and exchangeRate
uint256 ethFinalized; // final eth for claiming according to finalize exchange rate
- uint256 requestBlock; // block number of withdraw request
}
/// @custom:oz-upgrades-unsafe-allow constructor
@@ -98,13 +98,14 @@ contract UserWithdrawalManager is
if (assets < staderConfig.getMinWithdrawAmount() || assets > staderConfig.getMaxWithdrawAmount()) {
revert InvalidWithdrawAmount();
}
- if (requestIdsByUserAddress[_owner].length + 1 > maxNonRedeemedUserRequestCount) {
+ uint256[] storage _requestIdsByUserAddress = requestIdsByUserAddress[_owner];
+ if (_requestIdsByUserAddress.length + 1 > maxNonRedeemedUserRequestCount) {
revert MaxLimitOnWithdrawRequestCountReached();
}
IERC20Upgradeable(staderConfig.getETHxToken()).safeTransferFrom(msg.sender, (address(this)), _ethXAmount);
ethRequestedForWithdraw += assets;
- userWithdrawRequests[nextRequestId] = UserWithdrawInfo(payable(_owner), _ethXAmount, assets, 0, block.number);
- requestIdsByUserAddress[_owner].push(nextRequestId);
+ userWithdrawRequests[nextRequestId] = UserWithdrawInfo(payable(_owner), uint96(block.number), _ethXAmount, assets, 0);
+ _requestIdsByUserAddress.push(nextRequestId);
emit WithdrawRequestReceived(msg.sender, _owner, nextRequestId, _ethXAmount, assets);
nextRequestId++;
return nextRequestId - 1;
@@ -128,21 +129,22 @@ contract UserWithdrawalManager is
uint256 lockedEthXToBurn;
uint256 ethToSendToFinalizeRequest;
uint256 requestId;
+ uint256 requiredEth;
+ uint256 minBlockDelay = staderConfig.getMinBlockDelayToFinalizeWithdrawRequest();
uint256 pooledETH = poolManager.balance;
for (requestId = nextRequestIdToFinalize; requestId <= maxRequestIdToFinalize; ) {
UserWithdrawInfo memory userWithdrawInfo = userWithdrawRequests[requestId];
- uint256 requiredEth = userWithdrawInfo.ethExpected;
uint256 lockedEthX = userWithdrawInfo.ethXAmount;
- uint256 minEThRequiredToFinalizeRequest = Math.min(requiredEth, (lockedEthX * exchangeRate) / DECIMALS);
+ uint256 minEThRequiredToFinalizeRequest = Math.min(userWithdrawInfo.ethExpected, (lockedEthX * exchangeRate) / DECIMALS);
if (
(ethToSendToFinalizeRequest + minEThRequiredToFinalizeRequest > pooledETH) ||
- (userWithdrawInfo.requestBlock + staderConfig.getMinBlockDelayToFinalizeWithdrawRequest() >
+ (userWithdrawInfo.requestBlock + minBlockDelay >
block.number)
) {
break;
}
userWithdrawRequests[requestId].ethFinalized = minEThRequiredToFinalizeRequest;
- ethRequestedForWithdraw -= requiredEth;
+ requiredEth += userWithdrawInfo.ethExpected;
lockedEthXToBurn += lockedEthX;
ethToSendToFinalizeRequest += minEThRequiredToFinalizeRequest;
unchecked {
@@ -151,6 +153,7 @@ contract UserWithdrawalManager is
}
// at here, upto (requestId-1) is finalized
if (requestId > nextRequestIdToFinalize) {
+ ethRequestedForWithdraw = ethRequestedForWithdraw - requiredEth;
nextRequestIdToFinalize = requestId;
ETHx(staderConfig.getETHxToken()).burnFrom(address(this), lockedEthXToBurn);
IStaderStakePoolManager(poolManager).transferETHToUserWithdrawManager(ethToSendToFinalizeRequest);
@@ -166,8 +169,9 @@ contract UserWithdrawalManager is
if (_requestId >= nextRequestIdToFinalize) {
revert requestIdNotFinalized(_requestId);
}
- UserWithdrawInfo memory userRequest = userWithdrawRequests[_requestId];
- if (msg.sender != userRequest.owner) {
+ UserWithdrawInfo storage userRequest = userWithdrawRequests[_requestId];
+ address payable _owner = userRequest.owner;
+ if (msg.sender != _owner) {
revert CallerNotAuthorizedToRedeem();
}
// below is a default entry as no userRequest will be found for a redeemed request.
@@ -175,9 +179,9 @@ contract UserWithdrawalManager is
revert RequestAlreadyRedeemed(_requestId);
}
uint256 etherToTransfer = userRequest.ethFinalized;
- deleteRequestId(_requestId, userRequest.owner);
- sendValue(userRequest.owner, etherToTransfer);
- emit RequestRedeemed(msg.sender, userRequest.owner, etherToTransfer);
+ deleteRequestId(_requestId, _owner);
+ sendValue(_owner, etherToTransfer);
+ emit RequestRedeemed(msg.sender, _owner, etherToTransfer);
}
/// @notice return the list of ongoing withdraw requestIds for a user
@@ -205,8 +209,8 @@ contract UserWithdrawalManager is
// delete entry from userWithdrawRequests mapping and in requestIdsByUserAddress mapping
function deleteRequestId(uint256 _requestId, address _owner) internal {
delete (userWithdrawRequests[_requestId]);
- uint256 userRequestCount = requestIdsByUserAddress[_owner].length;
uint256[] storage requestIds = requestIdsByUserAddress[_owner];
+ uint256 userRequestCount = requestIds.length;
for (uint256 i; i < userRequestCount; ) {
if (_requestId == requestIds[i]) {
requestIds[i] = requestIds[userRequestCount - 1];
Final diff for IUserWithdrawalManager.sol
diff --git a/contracts/interfaces/IUserWithdrawalManager.sol b/contracts/interfaces/IUserWithdrawalManager.sol
index 82fc86b..bd5a574 100644
--- a/contracts/interfaces/IUserWithdrawalManager.sol
+++ b/contracts/interfaces/IUserWithdrawalManager.sol
@@ -52,10 +52,10 @@ interface IUserWithdrawalManager {
view
returns (
address payable owner,
+ uint96 requestTime,
uint256 ethXAmount,
uint256 ethExpected,
- uint256 ethFinalized,
- uint256 requestTime
+ uint256 ethFinalized
);
Final diff for ValidatorWithdrawalVault.sol
diff --git a/contracts/ValidatorWithdrawalVault.sol b/contracts/ValidatorWithdrawalVault.sol
index eb3de50..0f065b4 100644
--- a/contracts/ValidatorWithdrawalVault.sol
+++ b/contracts/ValidatorWithdrawalVault.sol
@@ -1,7 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.16;
- import './library/UtilLib.sol';
import './library/ValidatorStatus.sol';
import './VaultProxy.sol';
@@ -28,9 +27,19 @@ contract ValidatorWithdrawalVault is IValidatorWithdrawalVault {
}
function distributeRewards() external override {
- uint8 poolId = VaultProxy(payable(address(this))).poolId();
- uint256 validatorId = VaultProxy(payable(address(this))).id();
- IStaderConfig staderConfig = VaultProxy(payable(address(this))).staderConfig();
+ uint8 poolId;
+ uint256 validatorId;
+ IStaderConfig staderConfig;
+ assembly {
+ // sigs for "poolId()" + "id()" + "staderConfig()"
+ mstore(0x00, 0x490ffa35af640d0f3e0dc34e)
+ if iszero(staticcall(gas(), address(), 0x1c, 0x04, 0x20, 0x20)) {revert(0, 0)}
+ poolId := mload(0x20)
+ if iszero(staticcall(gas(), address(), 0x18, 0x04, 0x20, 0x20)) {revert(0, 0)}
+ validatorId := mload(0x20)
+ if iszero(staticcall(gas(), address(), 0x14, 0x04, 0x20, 0x20)) {revert(0, 0)}
+ staderConfig := mload(0x20)
+ }
uint256 totalRewards = address(this).balance;
if (!staderConfig.onlyOperatorRole(msg.sender) && totalRewards > staderConfig.getRewardsThreshold()) {
emit DistributeRewardFailed(totalRewards, staderConfig.getRewardsThreshold());
@@ -39,29 +48,46 @@ contract ValidatorWithdrawalVault is IValidatorWithdrawalVault {
if (totalRewards == 0) {
revert NotEnoughRewardToDistribute();
}
- (uint256 userShare, uint256 operatorShare, uint256 protocolShare) = IPoolUtils(staderConfig.getPoolUtils())
- .calculateRewardShare(poolId, totalRewards);
+ IPoolUtils poolUtils = IPoolUtils(staderConfig.getPoolUtils());
+ (uint256 userShare, uint256 operatorShare, uint256 protocolShare) = poolUtils.calculateRewardShare(poolId, totalRewards);
// Distribute rewards
IStaderStakePoolManager(staderConfig.getStakePoolManager()).receiveWithdrawVaultUserShare{value: userShare}();
UtilLib.sendValue(payable(staderConfig.getStaderTreasury()), protocolShare);
IOperatorRewardsCollector(staderConfig.getOperatorRewardsCollector()).depositFor{value: operatorShare}(
- getOperatorAddress(poolId, validatorId, staderConfig)
+ getOperatorAddress(validatorId, poolUtils.getNodeRegistry(poolId))
);
emit DistributedRewards(userShare, operatorShare, protocolShare);
}
function settleFunds() external override {
- uint8 poolId = VaultProxy(payable(address(this))).poolId();
- uint256 validatorId = VaultProxy(payable(address(this))).id();
- IStaderConfig staderConfig = VaultProxy(payable(address(this))).staderConfig();
- address nodeRegistry = IPoolUtils(staderConfig.getPoolUtils()).getNodeRegistry(poolId);
+ uint8 poolId;
+ uint256 validatorId;
+ IStaderConfig staderConfig;
+ IPoolUtils poolUtils;
+ address nodeRegistry;
+ assembly {
+ // sigs for "getNodeRegistry(uint8)" + "poolId()" + "id()" + "staderConfig()" + "getPoolUtils()"
+ mstore(0x00, 0x6ccb9d70490ffa35af640d0f3e0dc34e99d055c8)
+ if iszero(staticcall(gas(), address(), 0x18, 0x04, 0x20, 0x20)) {revert(0, 0)}
+ poolId := mload(0x20)
+ if iszero(staticcall(gas(), address(), 0x14, 0x04, 0x20, 0x20)) {revert(0, 0)}
+ validatorId := mload(0x20)
+ if iszero(staticcall(gas(), address(), 0x10, 0x04, 0x20, 0x20)) {revert(0, 0)}
+ staderConfig := mload(0x20)
+ if iszero(staticcall(gas(), staderConfig, 0xc, 0x04, 0x20, 0x20)) {revert(0, 0)}
+ poolUtils := mload(0x20)
+ mstore(0x20, poolId)
+ if iszero(staticcall(gas(), poolUtils, 0x1c, 0x24, 0x20, 0x20)) {revert(0, 0)}
+ nodeRegistry := mload(0x20)
+ }
if (msg.sender != nodeRegistry) {
revert CallerNotNodeRegistryContract();
}
- (uint256 userSharePrelim, uint256 operatorShare, uint256 protocolShare) = calculateValidatorWithdrawalShare();
+ (uint256 userSharePrelim, uint256 operatorShare, uint256 protocolShare) = _calculateValidatorWithdrawalShare(staderConfig, poolId, poolUtils);
- uint256 penaltyAmount = getUpdatedPenaltyAmount(poolId, validatorId, staderConfig);
+ IPenalty penalty = IPenalty(staderConfig.getPenaltyContract());
+ uint256 penaltyAmount = getUpdatedPenaltyAmount(validatorId, nodeRegistry, penalty);
if (operatorShare < penaltyAmount) {
ISDCollateral(staderConfig.getSDCollateral()).slashValidatorSD(validatorId, poolId);
@@ -73,11 +99,11 @@ contract ValidatorWithdrawalVault is IValidatorWithdrawalVault {
// Final settlement
vaultSettleStatus = true;
- IPenalty(staderConfig.getPenaltyContract()).markValidatorSettled(poolId, validatorId);
+ penalty.markValidatorSettled(poolId, validatorId);
IStaderStakePoolManager(staderConfig.getStakePoolManager()).receiveWithdrawVaultUserShare{value: userShare}();
UtilLib.sendValue(payable(staderConfig.getStaderTreasury()), protocolShare);
IOperatorRewardsCollector(staderConfig.getOperatorRewardsCollector()).depositFor{value: operatorShare}(
- getOperatorAddress(poolId, validatorId, staderConfig)
+ getOperatorAddress(validatorId, nodeRegistry)
);
emit SettledFunds(userShare, operatorShare, protocolShare);
}
@@ -91,10 +117,25 @@ contract ValidatorWithdrawalVault is IValidatorWithdrawalVault {
uint256 _protocolShare
)
{
- uint8 poolId = VaultProxy(payable(address(this))).poolId();
IStaderConfig staderConfig = VaultProxy(payable(address(this))).staderConfig();
+ return _calculateValidatorWithdrawalShare(
+ staderConfig,
+ VaultProxy(payable(address(this))).poolId(),
+ IPoolUtils(staderConfig.getPoolUtils())
+ );
+ }
+
+ function _calculateValidatorWithdrawalShare(IStaderConfig staderConfig, uint8 poolId, IPoolUtils poolUtils)
+ internal
+ view
+ returns (
+ uint256 _userShare,
+ uint256 _operatorShare,
+ uint256 _protocolShare
+ )
+ {
uint256 TOTAL_STAKED_ETH = staderConfig.getStakedEthPerNode();
- uint256 collateralETH = getCollateralETH(poolId, staderConfig); // 0, incase of permissioned NOs
+ uint256 collateralETH = getCollateralETH(poolId, poolUtils); // 0, incase of permissioned NOs
uint256 usersETH = TOTAL_STAKED_ETH - collateralETH;
uint256 contractBalance = address(this).balance;
@@ -113,9 +154,7 @@ contract ValidatorWithdrawalVault is IValidatorWithdrawalVault {
_userShare = usersETH;
}
if (totalRewards > 0) {
- (uint256 userReward, uint256 operatorReward, uint256 protocolReward) = IPoolUtils(
- staderConfig.getPoolUtils()
- ).calculateRewardShare(poolId, totalRewards);
+ (uint256 userReward, uint256 operatorReward, uint256 protocolReward) = poolUtils.calculateRewardShare(poolId, totalRewards);
_userShare += userReward;
_operatorShare += operatorReward;
_protocolShare += protocolReward;
@@ -124,28 +163,28 @@ contract ValidatorWithdrawalVault is IValidatorWithdrawalVault {
// HELPER METHODS
- function getCollateralETH(uint8 _poolId, IStaderConfig _staderConfig) internal view returns (uint256) {
- return IPoolUtils(_staderConfig.getPoolUtils()).getCollateralETH(_poolId);
+ function getCollateralETH(uint8 _poolId, IPoolUtils poolUtils) internal view returns (uint256) {
+ return poolUtils.getCollateralETH(_poolId);
}
function getOperatorAddress(
- uint8 _poolId,
uint256 _validatorId,
- IStaderConfig _staderConfig
+ address nodeRegistry
) internal view returns (address) {
- return UtilLib.getOperatorAddressByValidatorId(_poolId, _validatorId, _staderConfig);
+ (, , , , uint256 operatorId, , , ) = INodeRegistry(nodeRegistry).validatorRegistry(_validatorId);
+ (, , , , address operatorAddress) = INodeRegistry(nodeRegistry).operatorStructById(operatorId);
+ return operatorAddress;
}
function getUpdatedPenaltyAmount(
- uint8 _poolId,
uint256 _validatorId,
- IStaderConfig _staderConfig
+ address nodeRegistry,
+ IPenalty penalty
) internal returns (uint256) {
- address nodeRegistry = IPoolUtils(_staderConfig.getPoolUtils()).getNodeRegistry(_poolId);
(, bytes memory pubkey, , , , , , ) = INodeRegistry(nodeRegistry).validatorRegistry(_validatorId);
bytes[] memory pubkeyArray = new bytes[](1);
pubkeyArray[0] = pubkey;
- IPenalty(_staderConfig.getPenaltyContract()).updateTotalPenaltyAmount(pubkeyArray);
- return IPenalty(_staderConfig.getPenaltyContract()).totalPenaltyAmount(pubkey);
+ penalty.updateTotalPenaltyAmount(pubkeyArray);
+ return penalty.totalPenaltyAmount(pubkey);
}
}
Final diff for UtilLib.sol
diff --git a/contracts/library/UtilLib.sol b/contracts/library/UtilLib.sol
index 75b2bc2..11e1fbc 100644
--- a/contracts/library/UtilLib.sol
+++ b/contracts/library/UtilLib.sol
@@ -53,7 +53,7 @@ library UtilLib {
IStaderConfig _staderConfig
) internal view returns (bytes memory) {
address nodeRegistry = IPoolUtils(_staderConfig.getPoolUtils()).getNodeRegistry(_poolId);
- (, bytes memory pubkey, , , address withdrawVaultAddress, , , ) = INodeRegistry(nodeRegistry).validatorRegistry(
+ (, bytes memory pubkey, , , , address withdrawVaultAddress, , ) = INodeRegistry(nodeRegistry).validatorRegistry(
_validatorId
);
if (_addr != withdrawVaultAddress) {
@@ -69,7 +69,7 @@ library UtilLib {
IStaderConfig _staderConfig
) internal view returns (address) {
address nodeRegistry = IPoolUtils(_staderConfig.getPoolUtils()).getNodeRegistry(_poolId);
- (, , , , address withdrawVaultAddress, uint256 operatorId, , ) = INodeRegistry(nodeRegistry).validatorRegistry(
+ (, , , , uint256 operatorId, address withdrawVaultAddress, , ) = INodeRegistry(nodeRegistry).validatorRegistry(
_validatorId
);
if (_addr != withdrawVaultAddress) {
@@ -86,7 +86,7 @@ library UtilLib {
IStaderConfig _staderConfig
) internal view {
address nodeRegistry = IPoolUtils(_staderConfig.getPoolUtils()).getNodeRegistry(_poolId);
- (, , , , address withdrawVaultAddress, , , ) = INodeRegistry(nodeRegistry).validatorRegistry(_validatorId);
+ (, , , , , address withdrawVaultAddress, , ) = INodeRegistry(nodeRegistry).validatorRegistry(_validatorId);
if (_addr != withdrawVaultAddress) {
revert CallerNotWithdrawVault();
}
@@ -98,7 +98,7 @@ library UtilLib {
IStaderConfig _staderConfig
) internal view returns (address) {
address nodeRegistry = IPoolUtils(_staderConfig.getPoolUtils()).getNodeRegistry(_poolId);
- (, , , , , uint256 operatorId, , ) = INodeRegistry(nodeRegistry).validatorRegistry(_validatorId);
+ (, , , , uint256 operatorId, , , ) = INodeRegistry(nodeRegistry).validatorRegistry(_validatorId);
(, , , , address operatorAddress) = INodeRegistry(nodeRegistry).operatorStructById(operatorId);
return operatorAddress;
@@ -148,7 +148,7 @@ library UtilLib {
uint8 poolId = IPoolUtils(_staderConfig.getPoolUtils()).getValidatorPoolId(_pubkey);
address nodeRegistry = IPoolUtils(_staderConfig.getPoolUtils()).getNodeRegistry(poolId);
uint256 validatorId = INodeRegistry(nodeRegistry).validatorIdByPubkey(_pubkey);
- (, , , , address withdrawVaultAddress, , , ) = INodeRegistry(nodeRegistry).validatorRegistry(validatorId);
+ (, , , , , address withdrawVaultAddress, , ) = INodeRegistry(nodeRegistry).validatorRegistry(validatorId);
return IVaultProxy(withdrawVaultAddress).vaultSettleStatus();
}