Inherit asset decimals in ERC4626 (#3639)
This commit is contained in:
@ -26,13 +26,27 @@ import "../../../utils/math/Math.sol";
|
||||
abstract contract ERC4626 is ERC20, IERC4626 {
|
||||
using Math for uint256;
|
||||
|
||||
IERC20Metadata private immutable _asset;
|
||||
IERC20 private immutable _asset;
|
||||
uint8 private immutable _decimals;
|
||||
|
||||
/**
|
||||
* @dev Set the underlying asset contract. This must be an ERC20-compatible contract (ERC20 or ERC777).
|
||||
*/
|
||||
constructor(IERC20Metadata asset_) {
|
||||
constructor(IERC20 asset_) {
|
||||
uint8 decimals_;
|
||||
try IERC20Metadata(address(asset_)).decimals() returns (uint8 value) {
|
||||
decimals_ = value;
|
||||
} catch {
|
||||
decimals_ = super.decimals();
|
||||
}
|
||||
|
||||
_asset = asset_;
|
||||
_decimals = decimals_;
|
||||
}
|
||||
|
||||
/** @dev See {IERC20Metadata-decimals}. */
|
||||
function decimals() public view virtual override(IERC20Metadata, ERC20) returns (uint8) {
|
||||
return _decimals;
|
||||
}
|
||||
|
||||
/** @dev See {IERC4626-asset}. */
|
||||
@ -153,19 +167,41 @@ abstract contract ERC4626 is ERC20, IERC4626 {
|
||||
uint256 supply = totalSupply();
|
||||
return
|
||||
(assets == 0 || supply == 0)
|
||||
? assets.mulDiv(10**decimals(), 10**_asset.decimals(), rounding)
|
||||
? _initialConvertToShares(assets, rounding)
|
||||
: assets.mulDiv(supply, totalAssets(), rounding);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Internal conversion function (from assets to shares) to apply when the vault is empty.
|
||||
*
|
||||
* NOTE: Make sure to keep this function consistent with {_initialConvertToAssets} when overriding it.
|
||||
*/
|
||||
function _initialConvertToShares(
|
||||
uint256 assets,
|
||||
Math.Rounding /*rounding*/
|
||||
) internal view virtual returns (uint256 shares) {
|
||||
return assets;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Internal conversion function (from shares to assets) with support for rounding direction.
|
||||
*/
|
||||
function _convertToAssets(uint256 shares, Math.Rounding rounding) internal view virtual returns (uint256 assets) {
|
||||
uint256 supply = totalSupply();
|
||||
return
|
||||
(supply == 0)
|
||||
? shares.mulDiv(10**_asset.decimals(), 10**decimals(), rounding)
|
||||
: shares.mulDiv(totalAssets(), supply, rounding);
|
||||
(supply == 0) ? _initialConvertToAssets(shares, rounding) : shares.mulDiv(totalAssets(), supply, rounding);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Internal conversion function (from shares to assets) to apply when the vault is empty.
|
||||
*
|
||||
* NOTE: Make sure to keep this function consistent with {_initialConvertToShares} when overriding it.
|
||||
*/
|
||||
function _initialConvertToAssets(
|
||||
uint256 shares,
|
||||
Math.Rounding /*rounding*/
|
||||
) internal view virtual returns (uint256 assets) {
|
||||
return shares;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user