From 8c3046c958d5e4d96b28906408cf519838b5a16d Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Tue, 30 Jul 2024 14:13:21 +0200 Subject: [PATCH 1/5] Refactor ERC4626-maxRedeem to reflect preview functions overrides --- contracts/token/ERC20/extensions/ERC4626.sol | 38 ++++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/contracts/token/ERC20/extensions/ERC4626.sol b/contracts/token/ERC20/extensions/ERC4626.sol index c71b14ad48c..7b6adeff271 100644 --- a/contracts/token/ERC20/extensions/ERC4626.sol +++ b/contracts/token/ERC20/extensions/ERC4626.sol @@ -97,77 +97,77 @@ abstract contract ERC4626 is ERC20, IERC4626 { } /** + * @inheritdoc ERC20 + * * @dev Decimals are computed by adding the decimal offset on top of the underlying asset's decimals. This * "original" value is cached during construction of the vault contract. If this read operation fails (e.g., the * asset has not been created yet), a default of 18 is used to represent the underlying asset's decimals. - * - * See {IERC20Metadata-decimals}. */ function decimals() public view virtual override(IERC20Metadata, ERC20) returns (uint8) { 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) { From b237dc19d9c7194d94e567fbff4714c2f584cfd9 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Tue, 30 Jul 2024 14:17:46 +0200 Subject: [PATCH 2/5] change inheritdoc --- contracts/token/ERC20/extensions/ERC4626.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/token/ERC20/extensions/ERC4626.sol b/contracts/token/ERC20/extensions/ERC4626.sol index 7b6adeff271..3ad8b30a492 100644 --- a/contracts/token/ERC20/extensions/ERC4626.sol +++ b/contracts/token/ERC20/extensions/ERC4626.sol @@ -97,7 +97,7 @@ abstract contract ERC4626 is ERC20, IERC4626 { } /** - * @inheritdoc ERC20 + * @inheritdoc IERC20Metadata * * @dev Decimals are computed by adding the decimal offset on top of the underlying asset's decimals. This * "original" value is cached during construction of the vault contract. If this read operation fails (e.g., the From bce690397d70f3e231a7f01246d0c6b1cefcc43b Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Tue, 30 Jul 2024 15:52:36 +0200 Subject: [PATCH 3/5] add changeset --- .changeset/shiny-dolphins-lick.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/shiny-dolphins-lick.md 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. From 5af6775409964b6e801c0bcb027db701df1ed070 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Tue, 30 Jul 2024 17:08:57 +0200 Subject: [PATCH 4/5] Update contracts/token/ERC20/extensions/ERC4626.sol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ernesto GarcĂ­a --- contracts/token/ERC20/extensions/ERC4626.sol | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contracts/token/ERC20/extensions/ERC4626.sol b/contracts/token/ERC20/extensions/ERC4626.sol index 3ad8b30a492..a0c9d37ac47 100644 --- a/contracts/token/ERC20/extensions/ERC4626.sol +++ b/contracts/token/ERC20/extensions/ERC4626.sol @@ -102,6 +102,8 @@ abstract contract ERC4626 is ERC20, IERC4626 { * @dev Decimals are computed by adding the decimal offset on top of the underlying asset's decimals. This * "original" value is cached during construction of the vault contract. If this read operation fails (e.g., the * asset has not been created yet), a default of 18 is used to represent the underlying asset's decimals. + * + * See {IERC20Metadata-decimals}. */ function decimals() public view virtual override(IERC20Metadata, ERC20) returns (uint8) { return _underlyingDecimals + _decimalsOffset(); From 757a25fac827feed9c19cc867c01b26bd09aeb54 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Tue, 30 Jul 2024 17:11:11 +0200 Subject: [PATCH 5/5] Update ERC4626.sol --- contracts/token/ERC20/extensions/ERC4626.sol | 2 -- 1 file changed, 2 deletions(-) diff --git a/contracts/token/ERC20/extensions/ERC4626.sol b/contracts/token/ERC20/extensions/ERC4626.sol index a0c9d37ac47..0115a6b3a89 100644 --- a/contracts/token/ERC20/extensions/ERC4626.sol +++ b/contracts/token/ERC20/extensions/ERC4626.sol @@ -97,8 +97,6 @@ abstract contract ERC4626 is ERC20, IERC4626 { } /** - * @inheritdoc IERC20Metadata - * * @dev Decimals are computed by adding the decimal offset on top of the underlying asset's decimals. This * "original" value is cached during construction of the vault contract. If this read operation fails (e.g., the * asset has not been created yet), a default of 18 is used to represent the underlying asset's decimals.