Repeated validator IDs could be passed in batchRevertExitRequest
Description
The function batchRevertExitRequest does not check if the _validatorIds passed to it are repeated nor does it check if an exit request has been previously requested for this validator ID. A malicious TNFT holder could use the same _validatorIds twice in an array, which would call IEtherFiNode(etherfiNode).updateNumExitRequests(0, 1); twice and would decrease the value of numExitRequestsByTnft by an unexpected amount. Or they could call batchRevertExitRequest with _validatorIds for which the exit request has not been previously requested, which would also decrease the value of numExitRequestsByTnft.
function batchRevertExitRequest(uint256[] calldata _validatorIds) external whenNotPaused {
for (uint256 i = 0; i < _validatorIds.length; i++) {
uint256 _validatorId = _validatorIds[i];
address etherfiNode = etherfiNodeAddress[_validatorId];
require (msg.sender == tnft.ownerOf(_validatorId), "NOT_TNFT_OWNER");
_updateEtherFiNode(_validatorId);
IEtherFiNode(etherfiNode).updateNumExitRequests(0, 1);
validatorInfos[_validatorId].exitRequestTimestamp = 0;
emit NodeExitRequestReverted(_validatorId);
}
}Impact
An attacker could call this numerous times to decrease the value of numExitRequestsByTnft to 0. Later, if a validator ID is unregistered, the call would revert due to an underflow in the following line if the validator is exited using an exit request:
if (_info.exitRequestTimestamp != 0) numExitRequestsByTnft -= 1;Recommendations
We recommend adding checks to ensure batchRevertExitRequest could only be called on a validator ID if an exit request has been previously requested for that ID.
Remediation
This issue has been acknowledged by EtherFi, and a fix was implemented in commit a15c35fd↗.