// Contract: DerpDAO
// Target function: function _mint(address account, uint256 amount) internal virtual override
 spender, amount);
            return true;
        }

        /**
        * @dev See {IERC20-transferFrom}.
        *
        * Emits an {Approval} event indicating the updated allowance. This is not
        * required by the EIP. See the note at the beginning of {ERC20}.
        *
        * Requirements:
        *
        * - `sender` and `recipient` cannot be the zero address.
        * - `sender` must have a balance of at least `amount`.
        * - the caller must have allowance for ``sender``'s tokens of at least
        * `amount`.
        */
        function transferFrom(
            address sender,
            address recipient,
            uint256 amount
        ) public virtual override returns (bool) {
            _transfer(sender, recipient, amount);

            uint256 currentAllowance = _allowances[sender][_msgSender()];
            require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
            unchecked {
                _approve(sender, _msgSender(), currentAllowance - amount);
            }

            return true;
        }

        /**
        * @dev Atomically increases the allowance granted to `spender` by the caller.
        *
        * This is an alternative to {approve} that can be used as a mitigation for
        * problems described in {IERC20-approve}.
        *
        * Emits an {Approval} event indicating the updated allowance.
        *
        * Requirements:
        *
        * - `spender` cannot be the zero address.
        */
        function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
            _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);
            return true;
        }

        /**
        * @dev Atomically decreases the allowance granted to `spender` by the caller.
        *
        * This is an alternative to {approve} that can be used as a mitigation for
        * problems described in {IERC20-approve}.
        *
        * Emits an {Approval} event indicating the updated allowance.
        *
        * Requirements:
        *
        * - `spender` cannot be the zero address.
        * - `spender` must have allowance for the caller of at least
        * `subtractedValue`.
        */
        function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
            uint256 currentAllowance = _allowances[_msgSender()][spender];
            require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
            unchecked {
                _approve(_msgSender(), spender, currentAllowance - subtractedValue);
            }

            return true;
        }

        /**
        * @dev Moves `amount` of tokens from `sender` to `recipient`.
        *
        * This internal function is equivalent to {transfer}, and can be used to
        * e.g. implement automatic token fees, slashing mechanisms, etc.
        *
        * Emits a {Transfer} event.
        *
        * Requirements:
        *
        * - `sender` cannot be the zero address.
        * - `recipient` cannot be the zero address.
        * - `sender` must have a balance of at least `amount`.
        */
        function _transfer(
            address sender,
            address recipient,
            uint256 amount
        ) internal virtual {
            require(sender != address(0), "ERC20: transfer from the zero address");
            require(recipient != address(0), "ERC20: transfer to the zero address");

            _beforeTokenTransfer(sender, recipient, amount);

            uint256 senderBalance = _balances[sender];
            require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
            unchecked {
                _balances[sender] = senderBalance - amount;
            }
            _balances[recipient] += amount;

            emit Transfer(sender, recipient, amount);

            _afterTokenTransfer(sender, recipient, amount);
        }

        /** @dev Creates `amount` tokens and assigns them to `account`, increasing
        * the total supply.
        *
        * Emits a {Transfer} event with `from` set to the zero address.
        *
        * Requirements:
        *
        * - `account` cannot be the zero address.
        */
        function _mint(address account, uint256 amount) internal virtual {
            require(account != address(0), "ERC20: mint to the zero address");

            _beforeTokenTransfer(address(0), account, amount);

            _totalSupply += amount;
            _balances[account] += amount;
            emit Transfer(address(0), account, amount);

            _afterTokenTransfer(address(0), account, amount);
        }

        /**
        * @dev Destroys `amount` tokens from `account`, reducing the
        * total supply.
        *
        * Emits a {Transfer} event with `to` set to the zero address.
        *
        * Requirements:
        *
        * - `account` cannot be the zero address.
        * - `account` must have at least `amount` tokens.
        */
        function _burn(address account, uint256 amount) internal virtual {
            require(account != address(0), "ERC20: burn from the zero address");

            _beforeTokenTransfer(account, address(0), amount);

            uint256 accountBalance = _balances[account];
            require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
            unchecked {
                _balances[account] = accountBalance - amount;
            }
            _totalSupply -= amount;

            emit Transfer(account, address(0), amount);

            _afterTokenTransfer(account, address(0), amount);
        }

        /**
        * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
        *
        * This internal function is equivalent to `approve`, and can be used to
        * e.g. set automatic allowances for certain subsystems, etc.
        *
        * Emits an {Approval} event.
        *
        * Requirements:
        *
        * - `owner` cannot be the zero address.
        * - `spender` cannot be the zero address.
        */
        function _approve(
            address owner,
            address spender,
            uint256 amount
        ) internal virtual {
            require(owner != address(0), "ERC20: approve from the zero address");
            require(spender != address(0), "ERC20: approve to the zero address");

            _allowances[owner][spender] = amount;
            emit Approval(owner, spender, amount);
        }

        /**
        * @dev Hook that is called before any transfer of tokens. This includes
        * minting and burning.
        *
        * Calling conditions:
        *
        * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
        * will be transferred to `to`.
        * - when `from` is zero, `amount` tokens will be minted for `to`.
        * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
        * - `from` and `to` are never both zero.
        *
        * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
        */
        function _beforeTokenTransfer(
            address from,
            address to,
            uint256 amount
        ) internal virtual {}

        /**
        * @dev Hook that is called after any transfer of tokens. This includes
        * minting and burning.
        *
        * Calling conditions:
        *
        * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
        * has been transferred to `to`.
        * - when `from` is zero, `amount` tokens have been minted for `to`.
        * - when `to` is zero, `amount` of ``from``'s tokens have been burned.
        * - `from` and `to` are never both zero.
        *
        * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
        */
        function _afterTokenTransfer(
            address from,
            address to,
            uint256 amount
        ) internal virtual {}
    }

    pragma solidity ^0.8.0;

    /**
    * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
    * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
    *
    * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
    * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't
    * need to send a transaction, and thus is not required to hold Ether at all.
    *
    * _Available since v3.4._
    */
    abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {
        using Counters for Counters.Counter;

        mapping(address => Counters.Counter) private _nonces;

        // solhint-disable-next-line var-name-mixedcase
        bytes32 private immutable _PERMIT_TYPEHASH =
            keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");

        /**
        * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `"1"`.
        *
        * It's a good idea to use the same `name` that is defined as the ERC20 token name.
        */
        constructor(string memory name) EIP712(name, "1") {}

        /**
        * @dev See {IERC20Permit-permit}.
        */
        function permit(
            address owner,
            address spender,
            uint256 value,
            uint256 deadline,
            uint8 v,
            bytes32 r,
            bytes32 s
        ) public virtual override {
            require(block.timestamp <= deadline, "ERC20Permit: expired deadline");

            bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));

            bytes32 hash = _hashTypedDataV4(structHash);

            address signer = ECDSA.recover(hash, v, r, s);
            require(signer == owner, "ERC20Permit: invalid signature");

            _approve(owner, spender, value);
        }

        /**
        * @dev See {IERC20Permit-nonces}.
        */
        function nonces(address owner) public view virtual override returns (uint256) {
            return _nonces[owner].current();
        }

        /**
        * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.
        */
        // solhint-disable-next-line func-name-mixedcase
        function DOMAIN_SEPARATOR() external view override returns (bytes32) {
            return _domainSeparatorV4();
        }

        /**
        * @dev "Consume a nonce": return the current value and increment.
        *
        * _Available since v4.1._
        */
        function _useNonce(address owner) internal virtual returns (uint256 current) {
            Counters.Counter storage nonce = _nonces[owner];
            current = nonce.current();
            nonce.increment();
        }
    }

    pragma solidity ^0.8.0;

    /**
    * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's,
    * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1.
    *
    * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module.
    *
    * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either
    * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting
    * power can be queried through the public accessors {getVotes} and {getPastVotes}.
    *
    * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it
    * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked.
    * Enabling self-delegation can easily be done by overriding the {delegates} function. Keep in mind however that this
    * will significantly increase the base gas cost of transfers.
    *
    * _Available since v4.2._
    */
    abstract contract ERC20Votes is ERC20Permit {
        struct Checkpoint {
            uint32 fromBlock;
            uint224 votes;
        }

        bytes32 private constant _DELEGATION_TYPEHASH =
            keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)");

        mapping(address => address) private _delegates;
        mapping(address => Checkpoint[]) private _checkpoints;
        Checkpoint[] private _totalSupplyCheckpoints;

        /**
        * @dev Emitted when an account changes their delegate.
        */
        event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);

        /**
        * @dev Emitted when a token transfer or delegate change results in changes to an account's voting power.
        */
        event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);

        /**
        * @dev Get the `pos`-th checkpoint for `account`.
        */
        function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) {
            return _checkpoints[account][pos];
        }

        /**
        * @dev Get number of checkpoints for `account`.
        */
        function numCheckpoints(address account) public view virtual returns (uint32) {
            return SafeCast.toUint32(_checkpoints[account].length);
        }

        /**
        * @dev Get the address `account` is currently delegating to.
        */
        function delegates(address account) public view virtual returns (address) {
            return _delegates[account];
        }

        /**
        * @dev Gets the current votes balance for `account`
        */
        function getVotes(address account) public view returns (uint256) {
            uint256 pos = _checkpoints[account].length;
            return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes;
        }

        /**
        * @dev Retrieve the number of votes for `account` at the end of `blockNumber`.
        *
        * Requirements:
        *
        * - `blockNumber` must have been already mined
        */
        function getPastVotes(address account, uint256 blockNumber) public view returns (uint256) {
            require(blockNumber < block.number, "ERC20Votes: block not yet mined");
            return _checkpointsLookup(_checkpoints[account], blockNumber);
        }

        /**
        * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances.
        * It is but NOT the sum of all the delegated votes!
        *
        * Requirements:
        *
        * - `blockNumber` must have been already mined
        */
        function getPastTotalSupply(uint256 blockNumber) public view returns (uint256) {
            require(blockNumber < block.number, "ERC20Votes: block not yet mined");
            return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber);
        }

        /**
        * @dev Lookup a value in a list of (sorted) checkpoints.
        */
        function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) {
            // We run a binary search to look for the earliest checkpoint taken after `blockNumber`.
            //
            // During the loop, the index of the wanted checkpoint remains in the range [low-1, high).
            // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant.
            // - If the middle checkpoint is after `blockNumber`, we look in [low, mid)
            // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high)
            // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not
            // out of bounds (in which case we're looking too far in the past and the result is 0).
            // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is
            // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out
            // the same.
            uint256 high = ckpts.length;
            uint256 low = 0;
            while (low < high) {
                uint256 mid = Math.average(low, high);
                if (ckpts[mid].fromBlock > blockNumber) {
                    high = mid;
                } else {
                    low = mid + 1;
                }
            }

            return high == 0 ? 0 : ckpts[high - 1].votes;
        }

        /**
        * @dev Delegate votes from the sender to `delegatee`.
        */
        function delegate(address delegatee) public virtual {
            _delegate(_msgSender(), delegatee);
        }

        /**
        * @dev Delegates votes from signer to `delegatee`
        */
        function delegateBySig(
            address delegatee,
            uint256 nonce,
            uint256 expiry,
            uint8 v,
            bytes32 r,
            bytes32 s
        ) public virtual {
            require(block.timestamp <= expiry, "ERC20Votes: signature expired");
            address signer = ECDSA.recover(
                _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))),
                v,
                r,
                s
            );
            require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce");
            _delegate(signer, delegatee);
        }

        /**
        * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1).
        */
        function _maxSupply() internal view virtual returns (uint224) {
            return type(uint224).max;
        }