Validators don't receive their collateral upon unsubscribing, and they must trust and wait for the oracles to publish a root that allows them to claim their collateral in the form of a reward. If the oracles and/or rewardsRoot are somehow compromised, the validator's collateral may be permanently lost. Additionally, validators must pay more gas to retrieve their collateral using claimRewards().
PoC
A validator must send ether equal to subscriptionCollateral to join the protocol, but when they leave they don't receive that collateral back:
function subscribeValidator(uint64 validatorID) external payable {
// Check collateral
require(
msg.value == subscriptionCollateral,
"DappnodeSmoothingPool::subscribeValidator: msg.value does not equal subscription collateral"
);
emit SubscribeValidator(
msg.sender,
subscriptionCollateral,
validatorID
);
}
...
function unsubscribeValidator(uint64 validatorID) external {
emit UnsubscribeValidator(msg.sender, validatorID);
}
Therefore, the only way for the validator to receive the collateral after unsubscribing is to wait for the collateral amount to be added as a reward for them in the rewards Merkle tree.
Github username: @0xDetermination Submission hash (on-chain): 0xdaafb805219e79cfca832079f3497e87547c741602099b0ada8f7ef82bc11d5f Severity: low
Description:
Impact
Validators don't receive their collateral upon unsubscribing, and they must trust and wait for the oracles to publish a root that allows them to claim their collateral in the form of a reward. If the oracles and/or
rewardsRoot
are somehow compromised, the validator's collateral may be permanently lost. Additionally, validators must pay more gas to retrieve their collateral usingclaimRewards()
.PoC
A validator must send ether equal to
subscriptionCollateral
to join the protocol, but when they leave they don't receive that collateral back:Therefore, the only way for the validator to receive the collateral after unsubscribing is to wait for the collateral amount to be added as a reward for them in the rewards Merkle tree.
Relevant Code
https://github.com/hats-finance/Smooth-0x64bc275b37e62eec81a00ecaecd2b9567058f990/blob/main/contracts/DappnodeSmoothingPool.sol#L277-L289 https://github.com/hats-finance/Smooth-0x64bc275b37e62eec81a00ecaecd2b9567058f990/blob/main/contracts/DappnodeSmoothingPool.sol#L353-L355
Recommended Fix
unsubscribeValidator()
should return the validator's collateral.