Improve handling and docs for ERC4626.decimals (#3733)

pull/3741/head
Francisco 2 years ago committed by GitHub
parent 9938a85558
commit 14f98dbb58
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 33
      contracts/token/ERC20/extensions/ERC4626.sol

@ -33,18 +33,33 @@ abstract contract ERC4626 is ERC20, IERC4626 {
* @dev Set the underlying asset contract. This must be an ERC20-compatible contract (ERC20 or ERC777).
*/
constructor(IERC20 asset_) {
uint8 decimals_;
try IERC20Metadata(address(asset_)).decimals() returns (uint8 value) {
decimals_ = value;
} catch {
decimals_ = super.decimals();
}
(bool success, uint8 assetDecimals) = _tryGetAssetDecimals(asset_);
_decimals = success ? assetDecimals : super.decimals();
_asset = asset_;
_decimals = decimals_;
}
/** @dev See {IERC20Metadata-decimals}. */
/**
* @dev Attempts to fetch the asset decimals. A return value of false indicates that the attempt failed in some way.
*/
function _tryGetAssetDecimals(IERC20 asset_) private returns (bool, uint8) {
(bool success, bytes memory encodedDecimals) = address(asset_).call(
abi.encodeWithSelector(IERC20Metadata.decimals.selector)
);
if (success && encodedDecimals.length >= 32) {
uint256 returnedDecimals = abi.decode(encodedDecimals, (uint256));
if (returnedDecimals <= type(uint8).max) {
return (true, uint8(returnedDecimals));
}
}
return (false, 0);
}
/**
* @dev Decimals are read from the underlying asset in the constructor and cached. If this fails (e.g., the asset
* has not been created yet), the cached value is set to a default obtained by `super.decimals()` (which depends on
* inheritance but is most likely 18). Override this function in order to set a guaranteed hardcoded value.
* See {IERC20Metadata-decimals}.
*/
function decimals() public view virtual override(IERC20Metadata, ERC20) returns (uint8) {
return _decimals;
}

Loading…
Cancel
Save