Strategy contracts
In addition to reviewing the 4626 vault strategies, we also checked the the external vaults with which the strategy contracts interact. It is important to validate that an attacker cannot manipulate a value in the external contracts that the strategies rely upon. For example, the function totalAssets
is used to calculate the number of shares and assets based on data from external contracts. If an attacker is able to manipulate the totalAssets
and call strategy functions before the state of the vault has been updated, then the number of shares issued to the attacker may be inflated.
For example, in the external contract AlpacaVault
, the work
function executes an external call before updating the vaultDebtVal
while also transferring out tokens. This is used when calculating totalToken
, which the AlpacaERC4626
contract relies upon in the totalAssets()
to calculate the total amount of underlying tokens the vault holds.
This can lead to a manipulation of totalAssets
during a work
call, inflating the shares minted. Currently, the use of a non-reentrant modifier for external functions, such as deposit
and withdraw
in AlpacaVault
, called from afterDeposit
and beforeWithdraw
prevents the attack from executing successfully. For more information on similar attacks, read this↗ and this↗.
function convertToShares(uint256 assets) public view returns (uint256) {
uint256 supply = totalSupply; // Saves an extra SLOAD if totalSupply is non-zero.
return supply == 0 ? assets : assets.mulDivDown(supply, totalAssets());
}
The share price is based on totalAssets()
function totalAssets() public view override returns (uint256) {
return alpacaVault.balanceOf(address(this)).mulDivDown(alpacaVault.totalToken(), alpacaVault.totalSupply());
}
That depends on totalToken()
, which can be artificially deflated.
Developers should be aware that an attacker may be able to use an external call from the vault to make a reentrant call or a call to an attacker controlled contract so a vault's external calls should be scrutinized. This is very important when external data/calls are used to calculate share prices of an 4626 vault.