Description:
Proxy contract enabling upgradeable smart contract patterns. Delegates calls to an implementation contract.
Blockchain: Ethereum
Source Code: View Code On The Blockchain
Solidity Source Code:
{{
"language": "Solidity",
"sources": {
"src/contracts/facilitators/gsm/Gsm.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
import {VersionedInitializable} from 'aave-v3-origin/contracts/misc/aave-upgradeability/VersionedInitializable.sol';
import {IERC20} from 'aave-v3-origin/contracts/dependencies/openzeppelin/contracts/IERC20.sol';
import {GPv2SafeERC20} from 'aave-v3-origin/contracts/dependencies/gnosis/contracts/GPv2SafeERC20.sol';
import {EIP712} from 'src/contracts/dependencies/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol';
import {SignatureChecker} from 'src/contracts/dependencies/openzeppelin-contracts/contracts/utils/cryptography/SignatureChecker.sol';
import {SafeCast} from 'src/contracts/dependencies/openzeppelin-contracts/contracts/utils/math/SafeCast.sol';
import {AccessControl} from 'src/contracts/dependencies/openzeppelin-contracts/contracts/access/AccessControl.sol';
import {IGhoFacilitator} from 'src/contracts/gho/interfaces/IGhoFacilitator.sol';
import {IGhoToken} from 'src/contracts/gho/interfaces/IGhoToken.sol';
import {IGsmPriceStrategy} from 'src/contracts/facilitators/gsm/priceStrategy/interfaces/IGsmPriceStrategy.sol';
import {IGsmFeeStrategy} from 'src/contracts/facilitators/gsm/feeStrategy/interfaces/IGsmFeeStrategy.sol';
import {IGhoReserve} from 'src/contracts/facilitators/gsm/interfaces/IGhoReserve.sol';
import {IGsm} from 'src/contracts/facilitators/gsm/interfaces/IGsm.sol';
/**
* @title Gsm
* @author Aave
* @notice GHO Stability Module. It provides buy/sell facilities to go to/from an underlying asset to/from GHO.
* @dev To be covered by a proxy contract.
*/
contract Gsm is AccessControl, VersionedInitializable, EIP712, IGsm {
using GPv2SafeERC20 for IERC20;
using SafeCast for uint256;
/// @inheritdoc IGsm
bytes32 public constant CONFIGURATOR_ROLE = keccak256('CONFIGURATOR_ROLE');
/// @inheritdoc IGsm
bytes32 public constant TOKEN_RESCUER_ROLE = keccak256('TOKEN_RESCUER_ROLE');
/// @inheritdoc IGsm
bytes32 public constant SWAP_FREEZER_ROLE = keccak256('SWAP_FREEZER_ROLE');
/// @inheritdoc IGsm
bytes32 public constant LIQUIDATOR_ROLE = keccak256('LIQUIDATOR_ROLE');
/// @inheritdoc IGsm
bytes32 public constant BUY_ASSET_WITH_SIG_TYPEHASH =
keccak256(
'BuyAssetWithSig(address originator,uint256 minAmount,address receiver,uint256 nonce,uint256 deadline)'
);
/// @inheritdoc IGsm
bytes32 public constant SELL_ASSET_WITH_SIG_TYPEHASH =
keccak256(
'SellAssetWithSig(address originator,uint256 maxAmount,address receiver,uint256 nonce,uint256 deadline)'
);
/// @inheritdoc IGsm
address public immutable GHO_TOKEN;
/// @inheritdoc IGsm
address public immutable UNDERLYING_ASSET;
/// @inheritdoc IGsm
address public immutable PRICE_STRATEGY;
/// @inheritdoc IGsm
mapping(address => uint256) public nonces;
address internal _ghoTreasury;
address internal _feeStrategy;
bool internal _isFrozen;
bool internal _isSeized;
uint128 internal _exposureCap;
uint128 internal _currentExposure;
uint128 internal _accruedFees;
address internal _ghoReserve;
/**
* @dev Require GSM to not be frozen for functions marked by this modifier
*/
modifier notFrozen() {
require(!_isFrozen, 'GSM_FROZEN');
_;
}
/**
* @dev Require GSM to not be seized for functions marked by this modifier
*/
modifier notSeized() {
require(!_isSeized, 'GSM_SEIZED');
_;
}
/**
* @dev Constructor
* @param ghoToken The address of the GHO token contract
* @param underlyingAsset The address of the collateral asset
* @param priceStrategy The address of the price strategy
*/
constructor(address ghoToken, address underlyingAsset, address priceStrategy) EIP712('GSM', '1') {
require(ghoToken != address(0), 'ZERO_ADDRESS_NOT_VALID');
require(underlyingAsset != address(0), 'ZERO_ADDRESS_NOT_VALID');
require(
IGsmPriceStrategy(priceStrategy).UNDERLYING_ASSET() == underlyingAsset,
'INVALID_PRICE_STRATEGY'
);
GHO_TOKEN = ghoToken;
UNDERLYING_ASSET = underlyingAsset;
PRICE_STRATEGY = priceStrategy;
}
/**
* @notice GSM initializer
* @param admin The address of the default admin role
* @param ghoTreasury The address of the GHO treasury
* @param exposureCap Maximum amount of user-supplied underlying asset in GSM
* @param ghoReserve The address of the GHO reserve to use tokens from
*/
function initialize(
address admin,
address ghoTreasury,
uint128 exposureCap,
address ghoReserve
) external initializer {
require(admin != address(0), 'ZERO_ADDRESS_NOT_VALID');
_grantRole(DEFAULT_ADMIN_ROLE, admin);
_grantRole(CONFIGURATOR_ROLE, admin);
_updateGhoTreasury(ghoTreasury);
_updateExposureCap(exposureCap);
_updateGhoReserve(ghoReserve);
}
/// @inheritdoc IGsm
function buyAsset(
uint256 minAmount,
address receiver
) external notFrozen notSeized returns (uint256, uint256) {
return _buyAsset(msg.sender, minAmount, receiver);
}
/// @inheritdoc IGsm
function buyAssetWithSig(
address originator,
uint256 minAmount,
address receiver,
uint256 deadline,
bytes calldata signature
) external notFrozen notSeized returns (uint256, uint256) {
require(deadline >= block.timestamp, 'SIGNATURE_DEADLINE_EXPIRED');
bytes32 digest = _hashTypedDataV4(
keccak256(
abi.encode(
BUY_ASSET_WITH_SIG_TYPEHASH,
originator,
minAmount,
receiver,
nonces[originator]++,
deadline
)
)
);
require(
SignatureChecker.isValidSignatureNow(originator, digest, signature),
'SIGNATURE_INVALID'
);
return _buyAsset(originator, minAmount, receiver);
}
/// @inheritdoc IGsm
function sellAsset(
uint256 maxAmount,
address receiver
) external notFrozen notSeized returns (uint256, uint256) {
return _sellAsset(msg.sender, maxAmount, receiver);
}
/// @inheritdoc IGsm
function sellAssetWithSig(
address originator,
uint256 maxAmount,
address receiver,
uint256 deadline,
bytes calldata signature
) external notFrozen notSeized returns (uint256, uint256) {
require(deadline >= block.timestamp, 'SIGNATURE_DEADLINE_EXPIRED');
bytes32 digest = _hashTypedDataV4(
keccak256(
abi.encode(
SELL_ASSET_WITH_SIG_TYPEHASH,
originator,
maxAmount,
receiver,
nonces[originator]++,
deadline
)
)
);
require(
SignatureChecker.isValidSignatureNow(originator, digest, signature),
'SIGNATURE_INVALID'
);
return _sellAsset(originator, maxAmount, receiver);
}
/// @inheritdoc IGsm
function rescueTokens(
address token,
address to,
uint256 amount
) external onlyRole(TOKEN_RESCUER_ROLE) {
require(amount > 0, 'INVALID_AMOUNT');
if (token == GHO_TOKEN) {
uint256 rescuableBalance = IERC20(token).balanceOf(address(this)) - _accruedFees;
require(rescuableBalance >= amount, 'INSUFFICIENT_GHO_TO_RESCUE');
}
if (token == UNDERLYING_ASSET) {
uint256 rescuableBalance = IERC20(token).balanceOf(address(this)) - _currentExposure;
require(rescuableBalance >= amount, 'INSUFFICIENT_EXOGENOUS_ASSET_TO_RESCUE');
}
IERC20(token).safeTransfer(to, amount);
emit TokensRescued(token, to, amount);
}
/// @inheritdoc IGsm
function setSwapFreeze(bool enable) external onlyRole(SWAP_FREEZER_ROLE) {
if (enable) {
require(!_isFrozen, 'GSM_ALREADY_FROZEN');
} else {
require(_isFrozen, 'GSM_ALREADY_UNFROZEN');
}
_isFrozen = enable;
emit SwapFreeze(msg.sender, enable);
}
/// @inheritdoc IGsm
function seize() external notSeized onlyRole(LIQUIDATOR_ROLE) returns (uint256) {
_isSeized = true;
_currentExposure = 0;
_updateExposureCap(0);
uint256 underlyingBalance = IERC20(UNDERLYING_ASSET).balanceOf(address(this));
if (underlyingBalance > 0) {
IERC20(UNDERLYING_ASSET).safeTransfer(_ghoTreasury, underlyingBalance);
}
emit Seized(msg.sender, _ghoTreasury, underlyingBalance, _getUsed());
return underlyingBalance;
}
/// @inheritdoc IGsm
function burnAfterSeize(uint256 amount) external onlyRole(LIQUIDATOR_ROLE) returns (uint256) {
require(_isSeized, 'GSM_NOT_SEIZED');
require(amount > 0, 'INVALID_AMOUNT');
uint256 usedGho = _getUsed();
if (amount > usedGho) {
amount = usedGho;
}
IGhoToken(GHO_TOKEN).transferFrom(msg.sender, address(this), amount);
IGhoReserve(_ghoReserve).restore(amount);
emit BurnAfterSeize(msg.sender, amount, (usedGho - amount));
return amount;
}
/// @inheritdoc IGsm
function updateFeeStrategy(address feeStrategy) external onlyRole(CONFIGURATOR_ROLE) {
_updateFeeStrategy(feeStrategy);
}
/// @inheritdoc IGsm
function updateExposureCap(uint128 exposureCap) external onlyRole(CONFIGURATOR_ROLE) {
_updateExposureCap(exposureCap);
}
/// @inheritdoc IGsm
function updateGhoReserve(address newGhoReserve) external onlyRole(CONFIGURATOR_ROLE) {
_updateGhoReserve(newGhoReserve);
}
/// @inheritdoc IGhoFacilitator
function distributeFeesToTreasury() public virtual override {
uint256 accruedFees = _accruedFees;
if (accruedFees > 0) {
_accruedFees = 0;
IERC20(GHO_TOKEN).transfer(_ghoTreasury, accruedFees);
emit FeesDistributedToTreasury(_ghoTreasury, GHO_TOKEN, accruedFees);
}
}
/// @inheritdoc IGhoFacilitator
function updateGhoTreasury(address newGhoTreasury) external override onlyRole(CONFIGURATOR_ROLE) {
_updateGhoTreasury(newGhoTreasury);
}
/// @inheritdoc IGsm
function DOMAIN_SEPARATOR() external view returns (bytes32) {
return _domainSeparatorV4();
}
/// @inheritdoc IGsm
function getGhoAmountForBuyAsset(
uint256 minAssetAmount
) external view returns (uint256, uint256, uint256, uint256) {
return _calculateGhoAmountForBuyAsset(minAssetAmount);
}
/// @inheritdoc IGsm
function getGhoAmountForSellAsset(
uint256 maxAssetAmount
) external view returns (uint256, uint256, uint256, uint256) {
return _calculateGhoAmountForSellAsset(maxAssetAmount);
}
/// @inheritdoc IGsm
function getAssetAmountForBuyAsset(
uint256 maxGhoAmount
) external view returns (uint256, uint256, uint256, uint256) {
bool withFee = _feeStrategy != address(0);
uint256 grossAmount = withFee
? IGsmFeeStrategy(_feeStrategy).getGrossAmountFromTotalBought(maxGhoAmount)
: maxGhoAmount;
// round down so maxGhoAmount is guaranteed
uint256 assetAmount = IGsmPriceStrategy(PRICE_STRATEGY).getGhoPriceInAsset(grossAmount, false);
uint256 finalGrossAmount = IGsmPriceStrategy(PRICE_STRATEGY).getAssetPriceInGho(
assetAmount,
true
);
uint256 finalFee = withFee ? IGsmFeeStrategy(_feeStrategy).getBuyFee(finalGrossAmount) : 0;
return (assetAmount, finalGrossAmount + finalFee, finalGrossAmount, finalFee);
}
/// @inheritdoc IGsm
function getAssetAmountForSellAsset(
uint256 minGhoAmount
) external view returns (uint256, uint256, uint256, uint256) {
bool withFee = _feeStrategy != address(0);
uint256 grossAmount = withFee
? IGsmFeeStrategy(_feeStrategy).getGrossAmountFromTotalSold(minGhoAmount)
: minGhoAmount;
// round up so minGhoAmount is guaranteed
uint256 assetAmount = IGsmPriceStrategy(PRICE_STRATEGY).getGhoPriceInAsset(grossAmount, true);
uint256 finalGrossAmount = IGsmPriceStrategy(PRICE_STRATEGY).getAssetPriceInGho(
assetAmount,
false
);
uint256 finalFee = withFee ? IGsmFeeStrategy(_feeStrategy).getSellFee(finalGrossAmount) : 0;
return (assetAmount, finalGrossAmount - finalFee, finalGrossAmount, finalFee);
}
/// @inheritdoc IGsm
function getAvailableUnderlyingExposure() external view returns (uint256) {
return _exposureCap > _currentExposure ? _exposureCap - _currentExposure : 0;
}
/// @inheritdoc IGsm
function getExposureCap() external view returns (uint128) {
return _exposureCap;
}
/// @inheritdoc IGsm
function getAvailableLiquidity() external view returns (uint256) {
return _currentExposure;
}
/// @inheritdoc IGsm
function getFeeStrategy() external view returns (address) {
return _feeStrategy;
}
/// @inheritdoc IGsm
function getAccruedFees() external view returns (uint256) {
return _accruedFees;
}
/// @inheritdoc IGsm
function getIsFrozen() external view returns (bool) {
return _isFrozen;
}
/// @inheritdoc IGsm
function getIsSeized() external view returns (bool) {
return _isSeized;
}
/// @inheritdoc IGsm
function getGhoReserve() external view returns (address) {
return _ghoReserve;
}
/// @inheritdoc IGsm
function getUsed() external view returns (uint256) {
return _getUsed();
}
/// @inheritdoc IGsm
function getLimit() external view returns (uint256) {
return _getLimit();
}
/// @inheritdoc IGsm
function canSwap() external view returns (bool) {
return !_isFrozen && !_isSeized;
}
/// @inheritdoc IGhoFacilitator
function getGhoTreasury() external view override returns (address) {
return _ghoTreasury;
}
/// @inheritdoc IGsm
function GSM_REVISION() public pure virtual override returns (uint256) {
return 1;
}
/**
* @dev Buys an underlying asset with GHO
* @param originator The originator of the request
* @param minAmount The minimum amount of the underlying asset desired for purchase
* @param receiver The recipient address of the underlying asset being purchased
* @return The amount of underlying asset bought
* @return The amount of GHO sold by the user
*/
function _buyAsset(
address originator,
uint256 minAmount,
address receiver
) internal returns (uint256, uint256) {
(
uint256 assetAmount,
uint256 ghoSold,
uint256 grossAmount,
uint256 fee
) = _calculateGhoAmountForBuyAsset(minAmount);
_beforeBuyAsset(originator, assetAmount, receiver);
require(assetAmount > 0, 'INVALID_AMOUNT');
require(_currentExposure >= assetAmount, 'INSUFFICIENT_AVAILABLE_EXOGENOUS_ASSET_LIQUIDITY');
_currentExposure -= uint128(assetAmount);
_accruedFees += fee.toUint128();
IGhoToken(GHO_TOKEN).transferFrom(originator, address(this), ghoSold);
IGhoReserve(_ghoReserve).restore(grossAmount);
IERC20(UNDERLYING_ASSET).safeTransfer(receiver, assetAmount);
emit BuyAsset(originator, receiver, assetAmount, ghoSold, fee);
return (assetAmount, ghoSold);
}
/**
* @dev Hook that is called before `buyAsset`.
* @dev This can be used to add custom logic
* @param originator Originator of the request
* @param amount The amount of the underlying asset desired for purchase
* @param receiver Recipient address of the underlying asset being purchased
*/
function _beforeBuyAsset(address originator, uint256 amount, address receiver) internal virtual {}
/**
* @dev Sells an underlying asset for GHO
* @param originator The originator of the request
* @param maxAmount The maximum amount of the underlying asset desired to sell
* @param receiver The recipient address of the GHO being purchased
* @return The amount of underlying asset sold
* @return The amount of GHO bought by the user
*/
function _sellAsset(
address originator,
uint256 maxAmount,
address receiver
) internal returns (uint256, uint256) {
(
uint256 assetAmount,
uint256 ghoBought,
uint256 grossAmount,
uint256 fee
) = _calculateGhoAmountForSellAsset(maxAmount);
_beforeSellAsset(originator, assetAmount, receiver);
require(assetAmount > 0, 'INVALID_AMOUNT');
require(_currentExposure + assetAmount <= _exposureCap, 'EXOGENOUS_ASSET_EXPOSURE_TOO_HIGH');
_currentExposure += uint128(assetAmount);
_accruedFees += fee.toUint128();
IERC20(UNDERLYING_ASSET).safeTransferFrom(originator, address(this), assetAmount);
IGhoReserve(_ghoReserve).use(grossAmount);
IGhoToken(GHO_TOKEN).transfer(receiver, ghoBought);
emit SellAsset(originator, receiver, assetAmount, grossAmount, fee);
return (assetAmount, ghoBought);
}
/**
* @dev Hook that is called before `sellAsset`.
* @dev This can be used to add custom logic
* @param originator Originator of the request
* @param amount The amount of the underlying asset desired to sell
* @param receiver Recipient address of the GHO being purchased
*/
function _beforeSellAsset(
address originator,
uint256 amount,
address receiver
) internal virtual {}
/**
* @dev Returns the amount of GHO sold in exchange of buying underlying asset
* @param assetAmount The amount of underlying asset to buy
* @return The exact amount of asset the user purchases
* @return The total amount of GHO the user sells (gross amount in GHO plus fee)
* @return The gross amount of GHO
* @return The fee amount in GHO, applied on top of gross amount of GHO
*/
function _calculateGhoAmountForBuyAsset(
uint256 assetAmount
) internal view returns (uint256, uint256, uint256, uint256) {
bool withFee = _feeStrategy != address(0);
// pick the highest GHO amount possible for given asset amount
uint256 grossAmount = IGsmPriceStrategy(PRICE_STRATEGY).getAssetPriceInGho(assetAmount, true);
uint256 fee = withFee ? IGsmFeeStrategy(_feeStrategy).getBuyFee(grossAmount) : 0;
uint256 ghoSold = grossAmount + fee;
uint256 finalGrossAmount = withFee
? IGsmFeeStrategy(_feeStrategy).getGrossAmountFromTotalBought(ghoSold)
: ghoSold;
// pick the lowest asset amount possible for given GHO amount
uint256 finalAssetAmount = IGsmPriceStrategy(PRICE_STRATEGY).getGhoPriceInAsset(
finalGrossAmount,
false
);
uint256 finalFee = ghoSold - finalGrossAmount;
return (finalAssetAmount, finalGrossAmount + finalFee, finalGrossAmount, finalFee);
}
/**
* @dev Returns the amount of GHO bought in exchange of a given amount of underlying asset
* @param assetAmount The amount of underlying asset to sell
* @return The exact amount of asset the user sells
* @return The total amount of GHO the user buys (gross amount in GHO minus fee)
* @return The gross amount of GHO
* @return The fee amount in GHO, applied to the gross amount of GHO
*/
function _calculateGhoAmountForSellAsset(
uint256 assetAmount
) internal view returns (uint256, uint256, uint256, uint256) {
bool withFee = _feeStrategy != address(0);
// pick the lowest GHO amount possible for given asset amount
uint256 grossAmount = IGsmPriceStrategy(PRICE_STRATEGY).getAssetPriceInGho(assetAmount, false);
uint256 fee = withFee ? IGsmFeeStrategy(_feeStrategy).getSellFee(grossAmount) : 0;
uint256 ghoBought = grossAmount - fee;
uint256 finalGrossAmount = withFee
? IGsmFeeStrategy(_feeStrategy).getGrossAmountFromTotalSold(ghoBought)
: ghoBought;
// pick the highest asset amount possible for given GHO amount
uint256 finalAssetAmount = IGsmPriceStrategy(PRICE_STRATEGY).getGhoPriceInAsset(
finalGrossAmount,
true
);
uint256 finalFee = finalGrossAmount - ghoBought;
return (finalAssetAmount, finalGrossAmount - finalFee, finalGrossAmount, finalFee);
}
/**
* @dev Returns the amount of GHO currently used.
* @return The amount of GHO used
*/
function _getUsed() internal view returns (uint256) {
return IGhoReserve(_ghoReserve).getUsed(address(this));
}
/**
* @dev Returns the maximum amount of GHO that can be used.
* @return The usage limit of GHO
*/
function _getLimit() internal view returns (uint256) {
return IGhoReserve(_ghoReserve).getLimit(address(this));
}
/**
* @dev Returns the usage data of a specified entity.
* @return The usage limit of GHO
* @return The amount of GHO used
*/
function _getUsage() internal view returns (uint256, uint256) {
return IGhoReserve(_ghoReserve).getUsage(address(this));
}
/**
* @dev Updates Fee Strategy
* @param feeStrategy The address of the new Fee Strategy
*/
function _updateFeeStrategy(address feeStrategy) internal {
address oldFeeStrategy = _feeStrategy;
_feeStrategy = feeStrategy;
emit FeeStrategyUpdated(oldFeeStrategy, feeStrategy);
}
/**
* @dev Updates Exposure Cap
* @param exposureCap The value of the new Exposure Cap
*/
function _updateExposureCap(uint128 exposureCap) internal {
uint128 oldExposureCap = _exposureCap;
_exposureCap = exposureCap;
emit ExposureCapUpdated(oldExposureCap, exposureCap);
}
/**
* @dev Updates GHO Treasury Address
* @param newGhoTreasury The address of the new GHO Treasury
*/
function _updateGhoTreasury(address newGhoTreasury) internal {
require(newGhoTreasury != address(0), 'ZERO_ADDRESS_NOT_VALID');
address oldGhoTreasury = _ghoTreasury;
_ghoTreasury = newGhoTreasury;
emit GhoTreasuryUpdated(oldGhoTreasury, newGhoTreasury);
}
/**
* @dev Updates the address of GHO reserve
* @param newGhoReserve The address of the GHO reserve for the GSM
*/
function _updateGhoReserve(address newGhoReserve) internal {
require(newGhoReserve != address(0), 'ZERO_ADDRESS_NOT_VALID');
address oldReserve = _ghoReserve;
_ghoReserve = newGhoReserve;
IGhoToken(GHO_TOKEN).approve(oldReserve, 0);
IGhoToken(GHO_TOKEN).approve(newGhoReserve, type(uint256).max);
emit GhoReserveUpdated(oldReserve, newGhoReserve);
}
/// @inheritdoc VersionedInitializable
function getRevision() internal pure virtual override returns (uint256) {
return GSM_REVISION();
}
}
"
},
"lib/aave-v3-origin/src/contracts/misc/aave-upgradeability/VersionedInitializable.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
/**
* @title VersionedInitializable
* @author Aave, inspired by the OpenZeppelin Initializable contract
* @notice Helper contract to implement initializer functions. To use it, replace
* the constructor with a function that has the `initializer` modifier.
* @dev WARNING: Unlike constructors, initializer functions must be manually
* invoked. This applies both to deploying an Initializable contract, as well
* as extending an Initializable contract via inheritance.
* WARNING: When used with inheritance, manual care must be taken to not invoke
* a parent initializer twice, or ensure that all initializers are idempotent,
* because this is not dealt with automatically as with constructors.
*/
abstract contract VersionedInitializable {
/**
* @dev Indicates that the contract has been initialized.
*/
uint256 private lastInitializedRevision = 0;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private initializing;
/**
* @dev Modifier to use in the initializer function of a contract.
*/
modifier initializer() {
uint256 revision = getRevision();
require(
initializing || isConstructor() || revision > lastInitializedRevision,
'Contract instance has already been initialized'
);
bool isTopLevelCall = !initializing;
if (isTopLevelCall) {
initializing = true;
lastInitializedRevision = revision;
}
_;
if (isTopLevelCall) {
initializing = false;
}
}
/**
* @notice Returns the revision number of the contract
* @dev Needs to be defined in the inherited class as a constant.
* @return The revision number
*/
function getRevision() internal pure virtual returns (uint256);
/**
* @notice Returns true if and only if the function is running in the constructor
* @return True if the function is running in the constructor
*/
function isConstructor() private view returns (bool) {
// extcodesize checks the size of the code stored in an address, and
// address returns the current address. Since the code is still not
// deployed when running a constructor, any checks on its code size will
// yield zero, making it an effective way to detect if a contract is
// under construction or not.
uint256 cs;
//solium-disable-next-line
assembly {
cs := extcodesize(address())
}
return cs == 0;
}
// Reserved storage space to allow for layout changes in the future.
uint256[50] private ______gap;
}
"
},
"lib/aave-v3-origin/src/contracts/dependencies/openzeppelin/contracts/IERC20.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}
"
},
"lib/aave-v3-origin/src/contracts/dependencies/gnosis/contracts/GPv2SafeERC20.sol": {
"content": "// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity ^0.8.10;
import {IERC20} from '../../openzeppelin/contracts/IERC20.sol';
/// @title Gnosis Protocol v2 Safe ERC20 Transfer Library
/// @author Gnosis Developers
/// @dev Gas-efficient version of Openzeppelin's SafeERC20 contract.
library GPv2SafeERC20 {
/// @dev Wrapper around a call to the ERC20 function `transfer` that reverts
/// also when the token returns `false`.
function safeTransfer(IERC20 token, address to, uint256 value) internal {
bytes4 selector_ = token.transfer.selector;
// solhint-disable-next-line no-inline-assembly
assembly {
let freeMemoryPointer := mload(0x40)
mstore(freeMemoryPointer, selector_)
mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff))
mstore(add(freeMemoryPointer, 36), value)
if iszero(call(gas(), token, 0, freeMemoryPointer, 68, 0, 0)) {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
}
require(getLastTransferResult(token), 'GPv2: failed transfer');
}
/// @dev Wrapper around a call to the ERC20 function `transferFrom` that
/// reverts also when the token returns `false`.
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
bytes4 selector_ = token.transferFrom.selector;
// solhint-disable-next-line no-inline-assembly
assembly {
let freeMemoryPointer := mload(0x40)
mstore(freeMemoryPointer, selector_)
mstore(add(freeMemoryPointer, 4), and(from, 0xffffffffffffffffffffffffffffffffffffffff))
mstore(add(freeMemoryPointer, 36), and(to, 0xffffffffffffffffffffffffffffffffffffffff))
mstore(add(freeMemoryPointer, 68), value)
if iszero(call(gas(), token, 0, freeMemoryPointer, 100, 0, 0)) {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
}
require(getLastTransferResult(token), 'GPv2: failed transferFrom');
}
/// @dev Verifies that the last return was a successful `transfer*` call.
/// This is done by checking that the return data is either empty, or
/// is a valid ABI encoded boolean.
function getLastTransferResult(IERC20 token) private view returns (bool success) {
// NOTE: Inspecting previous return data requires assembly. Note that
// we write the return data to memory 0 in the case where the return
// data size is 32, this is OK since the first 64 bytes of memory are
// reserved by Solidy as a scratch space that can be used within
// assembly blocks.
// <https://docs.soliditylang.org/en/v0.7.6/internals/layout_in_memory.html>
// solhint-disable-next-line no-inline-assembly
assembly {
/// @dev Revert with an ABI encoded Solidity error with a message
/// that fits into 32-bytes.
///
/// An ABI encoded Solidity error has the following memory layout:
///
/// ------------+----------------------------------
/// byte range | value
/// ------------+----------------------------------
/// 0x00..0x04 | selector("Error(string)")
/// 0x04..0x24 | string offset (always 0x20)
/// 0x24..0x44 | string length
/// 0x44..0x64 | string value, padded to 32-bytes
function revertWithMessage(length, message) {
mstore(0x00, '\x08\xc3\x79\xa0')
mstore(0x04, 0x20)
mstore(0x24, length)
mstore(0x44, message)
revert(0x00, 0x64)
}
switch returndatasize()
// Non-standard ERC20 transfer without return.
case 0 {
// NOTE: When the return data size is 0, verify that there
// is code at the address. This is done in order to maintain
// compatibility with Solidity calling conventions.
// <https://docs.soliditylang.org/en/v0.7.6/control-structures.html#external-function-calls>
if iszero(extcodesize(token)) {
revertWithMessage(20, 'GPv2: not a contract')
}
success := 1
}
// Standard ERC20 transfer returning boolean success value.
case 32 {
returndatacopy(0, 0, returndatasize())
// NOTE: For ABI encoding v1, any non-zero value is accepted
// as `true` for a boolean. In order to stay compatible with
// OpenZeppelin's `SafeERC20` library which is known to work
// with the existing ERC20 implementation we care about,
// make sure we return success for any non-zero return value
// from the `transfer*` call.
success := iszero(iszero(mload(0)))
}
default {
revertWithMessage(31, 'GPv2: malformed transfer result')
}
}
}
}
"
},
"src/contracts/dependencies/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)
pragma solidity ^0.8.0;
import "./ECDSA.sol";
/**
* @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.
*
* The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,
* thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding
* they need in their contracts using a combination of `abi.encode` and `keccak256`.
*
* This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding
* scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA
* ({_hashTypedDataV4}).
*
* The implementation of the domain separator was designed to be as efficient as possible while still properly updating
* the chain id to protect against replay attacks on an eventual fork of the chain.
*
* NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method
* https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].
*
* _Available since v3.4._
*/
abstract contract EIP712 {
/* solhint-disable var-name-mixedcase */
// Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to
// invalidate the cached domain separator if the chain id changes.
bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;
uint256 private immutable _CACHED_CHAIN_ID;
address private immutable _CACHED_THIS;
bytes32 private immutable _HASHED_NAME;
bytes32 private immutable _HASHED_VERSION;
bytes32 private immutable _TYPE_HASH;
/* solhint-enable var-name-mixedcase */
/**
* @dev Initializes the domain separator and parameter caches.
*
* The meaning of `name` and `version` is specified in
* https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:
*
* - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.
* - `version`: the current major version of the signing domain.
*
* NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart
* contract upgrade].
*/
constructor(string memory name, string memory version) {
bytes32 hashedName = keccak256(bytes(name));
bytes32 hashedVersion = keccak256(bytes(version));
bytes32 typeHash = keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
);
_HASHED_NAME = hashedName;
_HASHED_VERSION = hashedVersion;
_CACHED_CHAIN_ID = block.chainid;
_CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);
_CACHED_THIS = address(this);
_TYPE_HASH = typeHash;
}
/**
* @dev Returns the domain separator for the current chain.
*/
function _domainSeparatorV4() internal view returns (bytes32) {
if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {
return _CACHED_DOMAIN_SEPARATOR;
} else {
return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);
}
}
function _buildDomainSeparator(
bytes32 typeHash,
bytes32 nameHash,
bytes32 versionHash
) private view returns (bytes32) {
return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));
}
/**
* @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this
* function returns the hash of the fully encoded EIP712 message for this domain.
*
* This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:
*
* ```solidity
* bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
* keccak256("Mail(address to,string contents)"),
* mailTo,
* keccak256(bytes(mailContents))
* )));
* address signer = ECDSA.recover(digest, signature);
* ```
*/
function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {
return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);
}
}
"
},
"src/contracts/dependencies/openzeppelin-contracts/contracts/utils/cryptography/SignatureChecker.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/SignatureChecker.sol)
pragma solidity ^0.8.0;
import "./ECDSA.sol";
import "../Address.sol";
import "../../interfaces/IERC1271.sol";
/**
* @dev Signature verification helper that can be used instead of `ECDSA.recover` to seamlessly support both ECDSA
* signatures from externally owned accounts (EOAs) as well as ERC1271 signatures from smart contract wallets like
* Argent and Gnosis Safe.
*
* _Available since v4.1._
*/
library SignatureChecker {
/**
* @dev Checks if a signature is valid for a given signer and data hash. If the signer is a smart contract, the
* signature is validated against that smart contract using ERC1271, otherwise it's validated using `ECDSA.recover`.
*
* NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus
* change through time. It could return true at block N and false at block N+1 (or the opposite).
*/
function isValidSignatureNow(
address signer,
bytes32 hash,
bytes memory signature
) internal view returns (bool) {
(address recovered, ECDSA.RecoverError error) = ECDSA.tryRecover(hash, signature);
if (error == ECDSA.RecoverError.NoError && recovered == signer) {
return true;
}
(bool success, bytes memory result) = signer.staticcall(
abi.encodeWithSelector(IERC1271.isValidSignature.selector, hash, signature)
);
return (success &&
result.length == 32 &&
abi.decode(result, (bytes32)) == bytes32(IERC1271.isValidSignature.selector));
}
}
"
},
"src/contracts/dependencies/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)
// This file was procedurally generated from scripts/generate/templates/SafeCast.js.
pragma solidity ^0.8.0;
/**
* @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow
* checks.
*
* Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
* easily result in undesired exploitation or bugs, since developers usually
* assume that overflows raise errors. `SafeCast` restores this intuition by
* reverting the transaction when such an operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*
* Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing
* all math on `uint256` and `int256` and then downcasting.
*/
library SafeCast {
/**
* @dev Returns the downcasted uint248 from uint256, reverting on
* overflow (when the input is greater than largest uint248).
*
* Counterpart to Solidity's `uint248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*
* _Available since v4.7._
*/
function toUint248(uint256 value) internal pure returns (uint248) {
require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits");
return uint248(value);
}
/**
* @dev Returns the downcasted uint240 from uint256, reverting on
* overflow (when the input is greater than largest uint240).
*
* Counterpart to Solidity's `uint240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*
* _Available since v4.7._
*/
function toUint240(uint256 value) internal pure returns (uint240) {
require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits");
return uint240(value);
}
/**
* @dev Returns the downcasted uint232 from uint256, reverting on
* overflow (when the input is greater than largest uint232).
*
* Counterpart to Solidity's `uint232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*
* _Available since v4.7._
*/
function toUint232(uint256 value) internal pure returns (uint232) {
require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits");
return uint232(value);
}
/**
* @dev Returns the downcasted uint224 from uint256, reverting on
* overflow (when the input is greater than largest uint224).
*
* Counterpart to Solidity's `uint224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*
* _Available since v4.2._
*/
function toUint224(uint256 value) internal pure returns (uint224) {
require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits");
return uint224(value);
}
/**
* @dev Returns the downcasted uint216 from uint256, reverting on
* overflow (when the input is greater than largest uint216).
*
* Counterpart to Solidity's `uint216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*
* _Available since v4.7._
*/
function toUint216(uint256 value) internal pure returns (uint216) {
require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits");
return uint216(value);
}
/**
* @dev Returns the downcasted uint208 from uint256, reverting on
* overflow (when the input is greater than largest uint208).
*
* Counterpart to Solidity's `uint208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*
* _Available since v4.7._
*/
function toUint208(uint256 value) internal pure returns (uint208) {
require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits");
return uint208(value);
}
/**
* @dev Returns the downcasted uint200 from uint256, reverting on
* overflow (when the input is greater than largest uint200).
*
* Counterpart to Solidity's `uint200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*
* _Available since v4.7._
*/
function toUint200(uint256 value) internal pure returns (uint200) {
require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits");
return uint200(value);
}
/**
* @dev Returns the downcasted uint192 from uint256, reverting on
* overflow (when the input is greater than largest uint192).
*
* Counterpart to Solidity's `uint192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*
* _Available since v4.7._
*/
function toUint192(uint256 value) internal pure returns (uint192) {
require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits");
return uint192(value);
}
/**
* @dev Returns the downcasted uint184 from uint256, reverting on
* overflow (when the input is greater than largest uint184).
*
* Counterpart to Solidity's `uint184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*
* _Available since v4.7._
*/
function toUint184(uint256 value) internal pure returns (uint184) {
require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits");
return uint184(value);
}
/**
* @dev Returns the downcasted uint176 from uint256, reverting on
* overflow (when the input is greater than largest uint176).
*
* Counterpart to Solidity's `uint176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*
* _Available since v4.7._
*/
function toUint176(uint256 value) internal pure returns (uint176) {
require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits");
return uint176(value);
}
/**
* @dev Returns the downcasted uint168 from uint256, reverting on
* overflow (when the input is greater than largest uint168).
*
* Counterpart to Solidity's `uint168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*
* _Available since v4.7._
*/
function toUint168(uint256 value) internal pure returns (uint168) {
require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits");
return uint168(value);
}
/**
* @dev Returns the downcasted uint160 from uint256, reverting on
* overflow (when the input is greater than largest uint160).
*
* Counterpart to Solidity's `uint160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*
* _Available since v4.7._
*/
function toUint160(uint256 value) internal pure returns (uint160) {
require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits");
return uint160(value);
}
/**
* @dev Returns the downcasted uint152 from uint256, reverting on
* overflow (when the input is greater than largest uint152).
*
* Counterpart to Solidity's `uint152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*
* _Available since v4.7._
*/
function toUint152(uint256 value) internal pure returns (uint152) {
require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits");
return uint152(value);
}
/**
* @dev Returns the downcasted uint144 from uint256, reverting on
* overflow (when the input is greater than largest uint144).
*
* Counterpart to Solidity's `uint144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*
* _Available since v4.7._
*/
function toUint144(uint256 value) internal pure returns (uint144) {
require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits");
return uint144(value);
}
/**
* @dev Returns the downcasted uint136 from uint256, reverting on
* overflow (when the input is greater than largest uint136).
*
* Counterpart to Solidity's `uint136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*
* _Available since v4.7._
*/
function toUint136(uint256 value) internal pure returns (uint136) {
require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits");
return uint136(value);
}
/**
* @dev Returns the downcasted uint128 from uint256, reverting on
* overflow (when the input is greater than largest uint128).
*
* Counterpart to Solidity's `uint128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*
* _Available since v2.5._
*/
function toUint128(uint256 value) internal pure returns (uint128) {
require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits");
return uint128(value);
}
/**
* @dev Returns the downcasted uint120 from uint256, reverting on
* overflow (when the input is greater than largest uint120).
*
* Counterpart to Solidity's `uint120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*
* _Available since v4.7._
*/
function toUint120(uint256 value) internal pure returns (uint120) {
require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits");
return uint120(value);
}
/**
* @dev Returns the downcasted uint112 from uint256, reverting on
* overflow (when the input is greater than largest uint112).
*
* Counterpart to Solidity's `uint112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*
* _Available since v4.7._
*/
function toUint112(uint256 value) internal pure returns (uint112) {
require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits");
return uint112(value);
}
/**
* @dev Returns the downcasted uint104 from uint256, reverting on
* overflow (when the input is greater than largest uint104).
*
* Counterpart to Solidity's `uint104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*
* _Available since v4.7._
*/
function toUint104(uint256 value) internal pure returns (uint104) {
require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits");
return uint104(value);
}
/**
* @dev Returns the downcasted uint96 from uint256, reverting on
* overflow (when the input is greater than largest uint96).
*
* Counterpart to Solidity's `uint96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*
* _Available since v4.2._
*/
function toUint96(uint256 value) internal pure returns (uint96) {
require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits");
return uint96(value);
}
/**
* @dev Returns the downcasted uint88 from uint256, reverting on
* overflow (when the input is greater than largest uint88).
*
* Counterpart to Solidity's `uint88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*
* _Available since v4.7._
*/
function toUint88(uint256 value) internal pure returns (uint88) {
require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits");
return uint88(value);
}
/**
* @dev Returns the downcasted uint80 from uint256, reverting on
* overflow (when the input is greater than largest uint80).
*
* Counterpart to Solidity's `uint80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*
* _Available since v4.7._
*/
function toUint80(uint256 value) internal pure returns (uint80) {
require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits");
return uint80(value);
}
/**
* @dev Returns the downcasted uint72 from uint256, reverting on
* overflow (when the input is greater than largest uint72).
*
* Counterpart to Solidity's `uint72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*
* _Available since v4.7._
*/
function toUint72(uint256 value) internal pure returns (uint72) {
require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits");
return uint72(value);
}
/**
* @dev Returns the downcasted uint64 from uint256, reverting on
* overflow (when the input is greater than largest uint64).
*
* Counterpart to Solidity's `uint64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*
* _Available since v2.5._
*/
function toUint64(uint256 value) internal pure returns (uint64) {
require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits");
return uint64(value);
}
/**
* @dev Returns the downcasted uint56 from uint256, reverting on
* overflow (when the input is greater than largest uint56).
*
* Counterpart to Solidity's `uint56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*
* _Available since v4.7._
*/
function toUint56(uint256 value) internal pure returns (uint56) {
require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits");
return uint56(value);
}
/**
* @dev Returns the downcasted uint48 from uint256, reverting on
* overflow (when the input is greater than largest uint48).
*
* Counterpart to Solidity's `uint48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*
* _Available since v4.7._
*/
function toUint48(uint256 value) internal pure returns (uint48) {
require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits");
return uint48(value);
}
/**
* @dev Returns the downcasted uint40 from uint256, reverting on
* overflow (when the input is greater than largest uint40).
*
* Counterpart to Solidity's `uint40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*
* _Available since v4.7._
*/
function toUint40(uint256 value) internal pure returns (uint40) {
require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits");
return uint40(value);
}
/**
* @dev Returns the downcasted uint32 from uint256, reverting on
* overflow (when the input is greater than largest uint32).
*
* Counterpart to Solidity's `uint32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*
* _Available since v2.5._
*/
function toUint32(uint256 value) internal pure returns (uint32) {
require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits");
return uint32(value);
}
/**
* @dev Returns the downcasted uint24 from uint256, reverting on
* overflow (when the input is greater than largest uint24).
*
* Counterpart to Solidity's `uint24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*
* _Available since v4.7._
*/
function toUint24(uint256 value) internal pure returns (uint24) {
require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits");
return uint24(value);
}
/**
* @dev Returns the downcasted uint16 from uint256, reverting on
* overflow (when the input is greater than largest uint16).
*
* Counterpart to Solidity's `uint16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*
* _Available since v2.5._
*/
function toUint16(uint256 value) internal pure returns (uint16) {
require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits");
return uint16(value);
}
/**
* @dev Returns the downcasted uint8 from uint256, reverting on
* overflow (when the input is greater than largest uint8).
*
* Counterpart to Solidity's `uint8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*
* _Available since v2.5._
*/
function toUint8(uint256 value) internal pure returns (uint8) {
require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits");
return uint8(value);
}
/**
* @dev Converts a signed int256 into an unsigned uint256.
*
* Requirements:
*
* - input must be greater than or equal to 0.
*
* _Available since v3.0._
*/
function toUint256(int256 value) internal pure returns (uint256) {
require(value >= 0, "SafeCast: value must be positive");
return uint256(value);
}
/**
* @dev Returns the downcasted int248 from int256, reverting on
* overflow (when the input is less than smallest int248 or
* greater than largest int248).
*
* Counterpart to Solidity's `int248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*
* _Available since v4.7._
*/
function toInt248(int256 value) internal pure returns (int248 downcasted) {
downcasted = int248(value);
require(downcasted == value, "SafeCast: value doesn't fit in 248 bits");
}
/**
* @dev Returns the downcasted int240 from int256, reverting on
* overflow (when the input is less than smallest int240 or
* greater than largest int240).
*
* Counterpart to Solidity's `int240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*
* _Available since v4.7._
*/
function toInt240(int256 value) internal pure returns (int240 downcasted) {
downcasted = int240(value);
require(downcasted == value, "SafeCast: value doesn't fit in 240 bits");
}
/**
* @dev Returns the downcasted int232 from int256, reverting on
* overflow (when the input is less than smallest int232 or
* greater than largest int232).
*
* Counterpart to Solidity's `int232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*
* _Available since v4.7._
*/
function toInt232(int256 value) internal pure returns (int232 downcasted) {
downcasted = int232(value);
require(downcasted == value, "SafeCast: value doesn't fit in 232 bits");
}
/**
* @dev Returns the downcasted int224 from int256, reverting on
* overflow (when the input is less than smallest int224 or
* greater than largest int224).
*
* Counterpart to Solidity's `int224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*
* _Available since v4.7._
*/
function toInt224(int256 value) internal pure returns (int224 downcasted) {
downcasted = int224(value);
require(downcasted == value, "SafeCast: value doesn't fit in 224 bits");
}
/**
* @dev Returns the downcasted int216 from int256, reverting on
* overflow (when the input is less than smallest int216 or
* greater than largest int216).
*
* Counterpart to Solidity's `int216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*
* _Available since v4.7._
*/
function toInt216(int256 value) internal pure returns (int216 downcasted) {
downcasted = int216(value);
require(downcasted == value, "SafeCast: value doesn't fit in 216 bits");
}
/**
* @dev Returns the downcasted int208 from int256, reverting on
* overflow (when the input is less than smallest int208 or
* greater than largest int208).
*
* Counterpart to Solidity's `int208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*
* _Available since v4.7._
*/
function toInt208(int256 value) internal pure returns (int208 downcasted) {
downcasted = int208(value);
require(downcasted == value, "SafeCast: value doesn't fit in 208 bits");
}
/**
* @dev Returns the downcasted int200 from int256, reverting on
* overflow (when the input is less than smallest int200 or
* greater than largest int200).
*
* Counterpart to Solidity's `int200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*
* _Available since v4.7._
*/
function toInt200(int256 value) internal pure returns (int200 downcasted) {
downcasted = int200(value);
require(downcasted == value, "SafeCast: value doesn't fit in 200 bits");
}
/**
* @dev Returns the downcasted int192 from int256, reverting on
* overflow (when the input is less than smallest int192 or
* greater than largest int192).
*
* Counterpart to Solidity's `int192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*
* _Available since v4.7._
*/
function toInt192(int256 value) internal pure returns (int192 downcasted) {
downcasted = int192(value);
require(downcasted == value, "SafeCast: value doesn't fit in 192 bits");
}
/**
* @dev Returns the downcasted int184 from int256, reverting on
* overflow (when the input is less than smallest int184 or
* greater than largest int184).
*
* Counterpart to Solidity's `int184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*
* _Available since v4.7._
*/
function toInt184(int256 value) internal pure returns (int184 downcasted) {
downcasted = int184(value);
require(downcasted == value, "SafeCast: value doesn't fit in 184 bits");
}
/**
* @dev Returns the downcasted int176 from int256, reverting on
* overflow (when the input is less than smallest int176 or
* greater than largest int176).
*
* Counterpart to Solidity's `int176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*
* _Available since v4.7._
*/
function toInt176(int256 value) internal pure returns (int176 downcasted) {
downcasted = int176(value);
require(downcasted == value, "SafeCast: value doesn't fit in 176 bits");
}
/**
* @dev Returns the downcasted int168 from int256, reverting on
* overflow (when the input is less than smallest int168 or
* greater than largest int168).
*
* Counterpart to Solidity's `int168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*
* _Available since v4.7._
*/
function toInt168(int256 value) internal pure returns (int168 downcasted) {
downcasted = int168(value);
require(downcasted == value, "SafeCast: value doesn't fit in 168 bits");
}
/**
* @dev Returns the downcasted int160 from int256, reverting on
* overflow (when the input is less than smallest int160 or
* greater than largest int160).
*
* Counterpart to Solidity's `int160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*
* _Available since v4.7._
*/
function toInt160(int256 value) internal pure returns (int160 downcasted) {
downcasted = int160(value);
require(downcasted == value, "SafeCast: value doesn't fit in 160 bits");
}
/**
* @dev Returns the downcasted int152 from int256, reverting on
* overflow (when the input is less than smallest int152 or
* greater than largest int152).
*
* Counterpart to Solidity's `int152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*
* _Available since v4.7._
*/
function toInt152(int256 value) internal pure returns (int152 downcasted) {
downcasted = int152(value);
require(downcasted == value, "SafeCast: value doesn't fit in 152 bits");
}
/**
* @dev Returns the downcasted int144 from int256, reverting on
* overflow (when the input is less than smallest int144 or
* greater than largest int144).
Submitted on: 2025-10-23 16:17:44
Comments
Log in to comment.
No comments yet.