HardhatDeFi
15,000 USDC
View results
Submission Details
Severity: high
Invalid

Unauthorized Fee Claim Transfers Due to Missing Balance Validation in transferFeeClaim()

Summary

The transferFeeClaim() function in the DIVA Protocol does not validate whether the sender actually owns the fee claim before transferring it. This means an attacker can transfer arbitrary fee claims without authorization, leading to fund theft.

Additionally, the batch function (batchTransferFeeClaim()) allows mass exploitation, making this vulnerability highly dangerous. Since the contract directly manipulates storage using assembly (fs.slot := position), any missing validation in _transferFeeClaim() could also lead to storage corruption, making legitimate fee claims unrecoverable.

* @notice Function to transfer fee claim from entitled address
* to another address
* @param _recipient Address of fee claim recipient
* @param _collateralToken Collateral token address
* @param _amount Amount (expressed as an integer with collateral token
* decimals) to transfer to recipient
*/
function transferFeeClaim(address _recipient, address _collateralToken, uint256 _amount) external;
/**
* @notice Batch version of `transferFeeClaim`
* @param _argsBatchTransferFeeClaim List containing collateral tokens,
* recipient addresses and amounts (expressed as an integer with collateral
* token decimals)
*/
function batchTransferFeeClaim(ArgsBatchTransferFeeClaim[] calldata _argsBatchTransferFeeClaim) external;

Implementation from Diva Protocol

function transferFeeClaim(
address _recipient,
address _collateralToken,
uint256 _amount
) external override nonReentrant {
_transferFeeClaim(
_recipient,
_collateralToken,
_amount,
LibDIVAStorage._feeClaimStorage()
);
}
function batchTransferFeeClaim(
ArgsBatchTransferFeeClaim[] calldata _argsBatchTransferFeeClaim
) external override nonReentrant {
uint256 len = _argsBatchTransferFeeClaim.length;
for (uint256 i; i < len; ) {
_transferFeeClaim(
_argsBatchTransferFeeClaim[i].recipient,
_argsBatchTransferFeeClaim[i].collateralToken,
_argsBatchTransferFeeClaim[i].amount,
LibDIVAStorage._feeClaimStorage()
);
unchecked {
++i;
}
}
}
function _feeClaimStorage()
internal
pure
returns (FeeClaimStorage storage fs)
{
bytes32 position = FEE_CLAIM_STORAGE_POSITION;
assembly {
fs.slot := position
}
}

Vulnerability Details

The transferFeeClaim() function does not verify whether the sender actually owns the specified fee claim before executing the transfer. This means that:

  1. Attackers can transfer arbitrary fee claims they do not own, effectively stealing funds.

  2. Batch execution (batchTransferFeeClaim()) allows mass exploitation, making it possible to drain multiple fee claims in a single transaction.

  3. Direct storage manipulation (fs.slot := position) makes unauthorized transfers even more dangerous, as it could lead to corruption of fee claim records, making legitimate claims unrecoverable.

Impact

Users can lose their fee claims without consent.

  • All fee claims in the system could be drained through repeated unauthorized transfers.

  • Storage corruption risk due to improper direct slot access, making recovery impossible.

  • Batch function amplifies damage, allowing attackers to automate large-scale withdrawals in one transaction.

Tools Used

Manual Review

Recommendations

Add ownership checks before executing transfers to prevent unauthorized fee claims.

Updates

Lead Judging Commences

bube Lead Judge 9 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.