Inconsistent interest calculations in Resonate
Description
In order to convert from the amount of underlying assets to shares, claimInterest
uses previewWithdraw(...)
:
function previewWithdraw(uint256 assets)
public
view
override
returns (uint256)
{
return convertToShares(assets);
}
[...]
function convertToShares(uint256 assets)
public
view
override
returns (uint256)
{
return (assets * yVault.totalSupply()) / getFreeFunds();
}
However, batchClaimInterest
uses the following to convert from assets to shares:
uint shareNormalization = vault.totalSupply() * PRECISION / vault.totalAssets();
[...]
uint totalSharesUnderlying = shareNormalization * amountUnderlying / PRECISION;
When interacting with the yearn vault, this results in a difference in interest calculations between the two functions - claimInterest(...)
uses getFreeFunds()
in the divisor while batchClaimInterest
uses vault.totalAssets();
.
Impact
The interest calculation of batchClaimInterest
would be inflated over claimInterest
by the difference in denominator in the asset-to-share conversion.
Recommendations
The difference is probably not intended by developers. It would be better to leverage composability and to use previewWithdraw(...)
in batchClaimInterest
. This would ensure batchClaimInterest
is consistent with claimInterest
across the different adapter implementations.
Remediation
Revest has followed the recommendation and is using previewWithdraw(...)
in commit da89259c00235fdab7edbcb638ec04f3e360ef48
.