abstract contract Permit is AbstractFiatTokenV2, EIP712Domain {
    bytes32
        public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;
    // = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)")

    mapping(address => uint256) private _permitNonces;

    /**
     * @notice Nonces for permit
     * @param owner Token owner's address (Authorizer)
     * @return Next nonce
     */
    function nonces(address owner) external view returns (uint256) {
        return _permitNonces[owner];
    }

    /**
     * @notice Verify a signed approval permit and execute if valid
     * @param owner     Token owner's address (Authorizer)
     * @param spender   Spender's address
     * @param value     Amount of allowance
     * @param deadline  The time at which this expires (unix time)
     * @param v         v of the signature
     * @param r         r of the signature
     * @param s         s of the signature
     */
    function _permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal {
        require(deadline >= now, "FiatTokenV2: permit is expired");

        bytes memory data = abi.encode(
            PERMIT_TYPEHASH,
            owner,
            spender,
            value,
            _permitNonces[owner]++,
            deadline
        );
        require(
            EIP712.recover(DOMAIN_SEPARATOR, v, r, s, data) == owner,
            "FiatTokenV2: invalid signature"
        );

        _approve(owner, spender, value);
    }
}
/**
 * @title Permit
 * @notice An alternative to approveWithAuthorization, provided for
 * compatibility with the draft EIP2612 proposed by Uniswap.
 * @dev Differences:
 * - Uses sequential nonce, which restricts transaction submission to one at a
 *   time, or else it will revert
 * - Has deadline (= validBefore - 1) but does not have validAfter
 * - Doesn't have a way to change allowance atomically to prevent ERC20 multiple
 *   withdrawal attacks
 */
function _permit(
    address owner,
    address spender,
    uint256 value,
    uint256 deadline,
    uint8 v,
    bytes32 r,
    bytes32 s
) internal {
    require(deadline >= now, "FiatTokenV2: permit is expired");

    bytes memory data = abi.encode(
        PERMIT_TYPEHASH,
        owner,
        spender,
        value,
        _permitNonces[owner]++,
        deadline
    );
    require(
        EIP712.recover(DOMAIN_SEPARATOR, v, r, s, data) == owner,
        "FiatTokenV2: invalid signature"
    );

    _approve(owner, spender, value);
}

/**
 * @notice Verify a signed approval permit and execute if valid
 * @param owner     Token owner's address (Authorizer)
 * @param spender   Spender's address
 * @param value     Amount of allowance
 * @param deadline  The time at which this expires (unix time)
 * @param v         v of the signature
 * @param r         r of the signature
 * @param s         s of the signature
 */