| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677 | // SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/ERC20FlashMint.sol)pragma solidity ^0.8.0;import "../../../interfaces/IERC3156.sol";import "../ERC20.sol";/** * @dev Implementation of the ERC3156 Flash loans extension, as defined in * https://eips.ethereum.org/EIPS/eip-3156[ERC-3156]. * * Adds the {flashLoan} method, which provides flash loan support at the token * level. By default there is no fee, but this can be changed by overriding {flashFee}. * * _Available since v4.1._ */abstract contract ERC20FlashMint is ERC20, IERC3156FlashLender {    bytes32 private constant _RETURN_VALUE = keccak256("ERC3156FlashBorrower.onFlashLoan");    /**     * @dev Returns the maximum amount of tokens available for loan.     * @param token The address of the token that is requested.     * @return The amont of token that can be loaned.     */    function maxFlashLoan(address token) public view override returns (uint256) {        return token == address(this) ? type(uint256).max - ERC20.totalSupply() : 0;    }    /**     * @dev Returns the fee applied when doing flash loans. By default this     * implementation has 0 fees. This function can be overloaded to make     * the flash loan mechanism deflationary.     * @param token The token to be flash loaned.     * @param amount The amount of tokens to be loaned.     * @return The fees applied to the corresponding flash loan.     */    function flashFee(address token, uint256 amount) public view virtual override returns (uint256) {        require(token == address(this), "ERC20FlashMint: wrong token");        // silence warning about unused variable without the addition of bytecode.        amount;        return 0;    }    /**     * @dev Performs a flash loan. New tokens are minted and sent to the     * `receiver`, who is required to implement the {IERC3156FlashBorrower}     * interface. By the end of the flash loan, the receiver is expected to own     * amount + fee tokens and have them approved back to the token contract itself so     * they can be burned.     * @param receiver The receiver of the flash loan. Should implement the     * {IERC3156FlashBorrower.onFlashLoan} interface.     * @param token The token to be flash loaned. Only `address(this)` is     * supported.     * @param amount The amount of tokens to be loaned.     * @param data An arbitrary datafield that is passed to the receiver.     * @return `true` is the flash loan was successful.     */    function flashLoan(        IERC3156FlashBorrower receiver,        address token,        uint256 amount,        bytes calldata data    ) public virtual override returns (bool) {        uint256 fee = flashFee(token, amount);        _mint(address(receiver), amount);        require(            receiver.onFlashLoan(msg.sender, token, amount, fee, data) == _RETURN_VALUE,            "ERC20FlashMint: invalid return value"        );        uint256 currentAllowance = allowance(address(receiver), address(this));        require(currentAllowance >= amount + fee, "ERC20FlashMint: allowance does not allow refund");        _approve(address(receiver), address(this), currentAllowance - amount - fee);        _burn(address(receiver), amount + fee);        return true;    }}
 |