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

`AaveDIVAWrapperCore::_getAccruedYieldPrivate` Yield Calculation Vulnerability

Summary

AaveDIVAWrapperCore::_getAccruedYieldPrivate Yield Calculation Vulnerability

Vulnerability Details

The current implementation of _getAccruedYieldPrivate assumes that the aToken balance will always be greater than or equal to the wToken supply, which may not hold true in all scenarios. This assumption creates a critical vulnerability in the yield calculation mechanism.

function _getAccruedYieldPrivate(address _collateralToken) private view returns (uint256) {
uint256 aTokenBalance = IERC20Metadata(IAave(_aaveV3Pool).getReserveData(_collateralToken).aTokenAddress)
.balanceOf(address(this));
uint256 wTokenSupply = IERC20Metadata(_collateralTokenToWToken[_collateralToken]).totalSupply();
return aTokenBalance > wTokenSupply ? aTokenBalance - wTokenSupply : 0;
}

Impact

  • Potential loss of accurate yield tracking

  • Masking of economic discrepancies

  • Risk of incorrect financial reporting

  • Incomplete representation of token interest accrual

Proof of Concept

describe('Yield Calculation Verification', function() {
it('Should investigate yield calculation limitations', async function() {
const { s, aTokenContract, wTokenContract } = await setupWithPool();
const aTokenBalance = await aTokenContract.balanceOf(s.aaveDIVAWrapper.target);
const wTokenSupply = await wTokenContract.totalSupply();
const calculatedYield = aTokenBalance > wTokenSupply
? aTokenBalance.sub(wTokenSupply)
: ethers.BigNumber.from(0);
expect(calculatedYield).to.be.a('BigNumber');
expect(calculatedYield).to.satisfy((yield) =>
yield.eq(0) || yield.gt(0),
'Yield calculation should be zero or positive'
);
});
});

Tools Used

Hardhat

Recommendations

function _getAccruedYieldPrivate(address _collateralToken) private view returns (uint256) {
+ uint256 currentExchangeRate = _calculatePreciseExchangeRate(_collateralToken);
+ uint256 initialSupply = IERC20Metadata(_collateralTokenToWToken[_collateralToken]).totalSupply();
+
+ uint256 calculatedYield = (currentExchangeRate * initialSupply) / 10**18 - initialSupply;
+
+ return calculatedYield > 0 ? calculatedYield : 0;
}
+function _calculatePreciseExchangeRate(address _collateralToken) private view returns (uint256) {
+ address aTokenAddress = IAave(_aaveV3Pool).getReserveData(_collateralToken).aTokenAddress;
+ uint256 aTokenBalance = IERC20Metadata(aTokenAddress).balanceOf(address(this));
+ uint256 initialSupply = IERC20Metadata(_collateralTokenToWToken[_collateralToken]).totalSupply();
+
+ return (aTokenBalance * 10**18) / initialSupply;
+}

This approach eliminates the risk of relying on an unverified assumption about token balances and creates a more resilient yield calculation mechanism.

Updates

Lead Judging Commences

bube Lead Judge 5 months ago
Submission Judgement Published
Invalidated
Reason: Known issue

Support

FAQs

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