diff --git a/.changeset/shiny-dolphins-lick.md b/.changeset/shiny-dolphins-lick.md new file mode 100644 index 00000000000..508e7f4304c --- /dev/null +++ b/.changeset/shiny-dolphins-lick.md @@ -0,0 +1,5 @@ +--- +'openzeppelin-solidity': minor +--- + +`ERC4626`: compute `maxWithdraw` using `maxRedeem` and `previewRedeem` so that changes to the preview functions affect the max functions. diff --git a/contracts/token/ERC20/extensions/ERC4626.sol b/contracts/token/ERC20/extensions/ERC4626.sol index c71b14ad48c..0115a6b3a89 100644 --- a/contracts/token/ERC20/extensions/ERC4626.sol +++ b/contracts/token/ERC20/extensions/ERC4626.sol @@ -107,67 +107,67 @@ abstract contract ERC4626 is ERC20, IERC4626 { return _underlyingDecimals + _decimalsOffset(); } - /** @dev See {IERC4626-asset}. */ + /// @inheritdoc IERC4626 function asset() public view virtual returns (address) { return address(_asset); } - /** @dev See {IERC4626-totalAssets}. */ + /// @inheritdoc IERC4626 function totalAssets() public view virtual returns (uint256) { return _asset.balanceOf(address(this)); } - /** @dev See {IERC4626-convertToShares}. */ + /// @inheritdoc IERC4626 function convertToShares(uint256 assets) public view virtual returns (uint256) { return _convertToShares(assets, Math.Rounding.Floor); } - /** @dev See {IERC4626-convertToAssets}. */ + /// @inheritdoc IERC4626 function convertToAssets(uint256 shares) public view virtual returns (uint256) { return _convertToAssets(shares, Math.Rounding.Floor); } - /** @dev See {IERC4626-maxDeposit}. */ + /// @inheritdoc IERC4626 function maxDeposit(address) public view virtual returns (uint256) { return type(uint256).max; } - /** @dev See {IERC4626-maxMint}. */ + /// @inheritdoc IERC4626 function maxMint(address) public view virtual returns (uint256) { return type(uint256).max; } - /** @dev See {IERC4626-maxWithdraw}. */ + /// @inheritdoc IERC4626 function maxWithdraw(address owner) public view virtual returns (uint256) { - return _convertToAssets(balanceOf(owner), Math.Rounding.Floor); + return previewRedeem(maxRedeem(owner)); } - /** @dev See {IERC4626-maxRedeem}. */ + /// @inheritdoc IERC4626 function maxRedeem(address owner) public view virtual returns (uint256) { return balanceOf(owner); } - /** @dev See {IERC4626-previewDeposit}. */ + /// @inheritdoc IERC4626 function previewDeposit(uint256 assets) public view virtual returns (uint256) { return _convertToShares(assets, Math.Rounding.Floor); } - /** @dev See {IERC4626-previewMint}. */ + /// @inheritdoc IERC4626 function previewMint(uint256 shares) public view virtual returns (uint256) { return _convertToAssets(shares, Math.Rounding.Ceil); } - /** @dev See {IERC4626-previewWithdraw}. */ + /// @inheritdoc IERC4626 function previewWithdraw(uint256 assets) public view virtual returns (uint256) { return _convertToShares(assets, Math.Rounding.Ceil); } - /** @dev See {IERC4626-previewRedeem}. */ + /// @inheritdoc IERC4626 function previewRedeem(uint256 shares) public view virtual returns (uint256) { return _convertToAssets(shares, Math.Rounding.Floor); } - /** @dev See {IERC4626-deposit}. */ + /// @inheritdoc IERC4626 function deposit(uint256 assets, address receiver) public virtual returns (uint256) { uint256 maxAssets = maxDeposit(receiver); if (assets > maxAssets) { @@ -180,7 +180,7 @@ abstract contract ERC4626 is ERC20, IERC4626 { return shares; } - /** @dev See {IERC4626-mint}. */ + /// @inheritdoc IERC4626 function mint(uint256 shares, address receiver) public virtual returns (uint256) { uint256 maxShares = maxMint(receiver); if (shares > maxShares) { @@ -193,7 +193,7 @@ abstract contract ERC4626 is ERC20, IERC4626 { return assets; } - /** @dev See {IERC4626-withdraw}. */ + /// @inheritdoc IERC4626 function withdraw(uint256 assets, address receiver, address owner) public virtual returns (uint256) { uint256 maxAssets = maxWithdraw(owner); if (assets > maxAssets) { @@ -206,7 +206,7 @@ abstract contract ERC4626 is ERC20, IERC4626 { return shares; } - /** @dev See {IERC4626-redeem}. */ + /// @inheritdoc IERC4626 function redeem(uint256 shares, address receiver, address owner) public virtual returns (uint256) { uint256 maxShares = maxRedeem(owner); if (shares > maxShares) {