Owners having valid permits might not be able to deposit or redeem assets/shares due to incorrect order of address validation in `_isValidSignature`
Audit: 2023-09-centrifuge-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-09-centrifuge/blob/main/src/token/ERC20.sol#L242
https://github.com/code-423n4/2023-09-centrifuge/blob/main/src/token/ERC20.sol#L242


# Vulnerability details

## Proof of Concept

`requestDepositWithPermit` requests asset deposit for a receiver to be included in the next epoch execution with a permit option.
`requestRedeemWithPermit` request share redemption for a receiver to be included in the next epoch execution with a permit option.

```solidity
File: LiquidityPool.sol

    /// @notice Similar to requestDeposit, but with a permit option.
    function requestDepositWithPermit(uint256 assets, address owner, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
        public
    {
        ERC20PermitLike(asset).permit(owner, address(investmentManager), assets, deadline, v, r, s);
        investmentManager.requestDeposit(assets, owner);
        emit DepositRequested(owner, assets);
    }

     ....................................................

      /// @notice Similar to requestRedeem, but with a permit option.
    function requestRedeemWithPermit(uint256 shares, address owner, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
        public
    {
        share.permit(owner, address(investmentManager), shares, deadline, v, r, s);
        investmentManager.requestRedeem(shares, owner);
        emit RedeemRequested(owner, shares);
    }
```
Both the above functions (requestDepositWithPermit & requestRedeemWithPermit) call the `permit` function with the correct parameters.

The `permit` function updates the nonce & calculates the digest with the necessary parameters & calls the `_isValidSignature` to verify the permit.

```solidity
File: ERC20.sol

       function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
        external
    {
        permit(owner, spender, value, deadline, abi.encodePacked(r, s, v));
    }
```

```solidity
233     require(_isValidSignature(owner, digest, signature), "ERC20/invalid-permit");
```
The issue lies in the first part of the `_isValidSignature`. 
The signature length is matched & the corresponding values of `v`, `r` & `s` are loaded from the memory & verified against the signer/owner address using `ecrecover`.

```solidity
File: ERC20.sol

       // --- Approve by signature ---
    function _isValidSignature(address signer, bytes32 digest, bytes memory signature) internal view returns (bool) {
        if (signature.length == 65) {
            bytes32 r;
            bytes32 s;
            uint8 v;
            assembly {
                r := mload(add(signature, 0x20))
                s := mload(add(signature, 0x40))
                v := byte(0, mload(add(signature, 0x60)))
            }
            if (signer == ecrecover(digest, v, r, s)) {
                return true;
            }
        }
```
But the problem arises in the order inside the `ecrecover()` as the order of `v`, `r` & `s` are different that is su