Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor ERC4626-maxWithdraw to reflect other functions overrides #5130

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/shiny-dolphins-lick.md
Original file line number Diff line number Diff line change
@@ -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.
34 changes: 17 additions & 17 deletions contracts/token/ERC20/extensions/ERC4626.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the change I propose.

In the case of ERC4626Fees, the fees inclusion in previewRedeem woudl reflect here.
Additionally, if maxRedeem is ever overriden, it would reflect here (but the inverse is not true)

}

/** @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) {
Expand All @@ -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) {
Expand All @@ -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) {
Expand All @@ -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) {
Expand Down