From 523a7b68dbb6169ddbff6bac40a7b76c073923c8 Mon Sep 17 00:00:00 2001 From: dglowinski Date: Thu, 28 Mar 2024 13:26:59 +0100 Subject: [PATCH] handle max functions compliance --- src/EVault/modules/Vault.sol | 14 +++++++++++--- src/EVault/shared/types/Assets.sol | 6 +++++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/EVault/modules/Vault.sol b/src/EVault/modules/Vault.sol index f010b48d..326519c0 100644 --- a/src/EVault/modules/Vault.sol +++ b/src/EVault/modules/Vault.sol @@ -40,6 +40,7 @@ abstract contract VaultModule is IVault, Base, AssetTransfers, BalanceUtils { } /// @inheritdoc IERC4626 + /// @dev Because `nonReentrantView` can revert, the function might be considered not fully compliant with ERC4626 function maxDeposit(address account) public view virtual nonReentrantView returns (uint256) { VaultCache memory vaultCache = loadVault(); @@ -52,12 +53,17 @@ abstract contract VaultModule is IVault, Base, AssetTransfers, BalanceUtils { } /// @inheritdoc IERC4626 + /// @dev If the hook on `mint` allows only certain amounts, maxMint function might not be fully compliant with ERC4626 + /// @dev Because `nonReentrantView` can revert, the function might be considered not fully compliant with ERC4626 function maxMint(address account) public view virtual nonReentrantView returns (uint256) { VaultCache memory vaultCache = loadVault(); - return validateAndCallHookView(vaultCache.hookedOps, OP_MINT) - ? maxDepositInternal(vaultCache, account).toAssets().toSharesDown(vaultCache).toUint() - : 0; + if (!validateAndCallHookView(vaultCache.hookedOps, OP_MINT)) return 0; + + // make sure to not revert on conversion + uint256 shares = maxDepositInternal(vaultCache, account).toAssets().toUint256SharesDown(vaultCache); + + return shares < MAX_SANE_AMOUNT ? shares : MAX_SANE_AMOUNT; } /// @inheritdoc IERC4626 @@ -67,6 +73,7 @@ abstract contract VaultModule is IVault, Base, AssetTransfers, BalanceUtils { } /// @inheritdoc IERC4626 + /// @dev Because `nonReentrantView` can revert, the function might be considered not fully compliant with ERC4626 function maxWithdraw(address owner) public view virtual nonReentrantView returns (uint256) { VaultCache memory vaultCache = loadVault(); @@ -82,6 +89,7 @@ abstract contract VaultModule is IVault, Base, AssetTransfers, BalanceUtils { } /// @inheritdoc IERC4626 + /// @dev Because `nonReentrantView` can revert, the function might be considered not fully compliant with ERC4626 function maxRedeem(address owner) public view virtual nonReentrantView returns (uint256) { return validateAndCallHookView(vaultStorage.hookedOps, OP_REDEEM) ? maxRedeemInternal(owner).toUint() : 0; } diff --git a/src/EVault/shared/types/Assets.sol b/src/EVault/shared/types/Assets.sol index 636623ed..4be7035e 100644 --- a/src/EVault/shared/types/Assets.sol +++ b/src/EVault/shared/types/Assets.sol @@ -17,9 +17,13 @@ library AssetsLib { } function toSharesDown(Assets amount, VaultCache memory vaultCache) internal pure returns (Shares) { + return TypesLib.toShares(toUint256SharesDown(amount, vaultCache)); + } + + function toUint256SharesDown(Assets amount, VaultCache memory vaultCache) internal pure returns (uint256) { (uint256 totalAssets, uint256 totalShares) = ConversionHelpers.conversionTotals(vaultCache); unchecked { - return TypesLib.toShares(amount.toUint() * totalShares / totalAssets); + return amount.toUint() * totalShares / totalAssets; } }