Unsuccessfully testing SignatureChecker.sol

Hello Moralis community.
It’s been a while since I’ve consulted you. I hope you are all very well. You are the best.

Let me tell you my problem.

I have been using the Externally Owned Accounts (EOA) signature without problems in a project. But in view of the new EIP-4337 I want to get up to speed with the ERC-1271 standard, which I don’t quite understand despite its simplicity, with the SignatureChecker.sol contract.

So far I was signing offchain and checking in my contracts without problems. It works very well.

I share code to how it validated inside my contract:

  function recoverSigner(bytes32 message, bytes memory sig) internal pure returns (address) {
        (uint8 v, bytes32 r, bytes32 s) = splitSignature(sig);

        return ecrecover(message, v, r, s);
    }

    /// signature methods.
    function splitSignature(bytes memory sig)
        internal
        pure
        returns (
            uint8 v,
            bytes32 r,
            bytes32 s
        )
    {
        require(sig.length == 65);

        assembly {
            // first 32 bytes, after the length prefix.
            r := mload(add(sig, 32))
            // second 32 bytes.
            s := mload(add(sig, 64))
            // final byte (first byte of the next 32 bytes).
            v := byte(0, mload(add(sig, 96)))
        }

        return (v, r, s);
    }

    /// builds a prefixed hash to mimic the behavior of eth_sign.
    function prefixed(bytes32 hash) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
    }

    function getPlayerHash(
        uint256 _idGame,
        uint256 _score,
        address _player
    ) public pure returns (bytes32) {
        return keccak256(abi.encodePacked(_idGame, _score, _player));
    }

    function security(
        uint256 _idGame,
        uint256 _score,
        bytes memory signature
    ) internal view returns (bool) {
        bytes32 message = prefixed(keccak256(abi.encodePacked(_idGame, _score, msg.sender)));

        require(recoverSigner(message, signature) == serverAddress, "Error");
        return true;
    }

Well. When I try to test the SignatureChecker contract, I can’t validate a single signature.

Here, my test contract:

/ SPDX-License-Identifier: MIT
import "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol";

pragma solidity ^0.8.0;


contract testingSignatureChecker  {

       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));
    }


        function test(address signer, bytes32 hash, bytes memory signature) external view  returns (bool) {

        return isValidSignatureNow(signer,  hash,  signature);
    }

        function getMessageHash(string memory _code) public pure returns (bytes32)
    {
        return keccak256(abi.encodePacked(_code));
    }

       function getMessageHashWithPrefixed(string memory _code) public pure returns (bytes32)
    {
        return prefixed(keccak256(abi.encodePacked(_code)));
    }

     /// builds a prefixed hash to mimic the behavior of eth_sign.
    function prefixed(bytes32 hash) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
    }


}

I create the hashes with the two types of functions that I have prepared in the contract, with prefix and without prefix:

   function getMessageHash(string memory _code) public pure returns (bytes32)
    {
        return keccak256(abi.encodePacked(_code));
    }

       function getMessageHashWithPrefixed(string memory _code) public pure returns (bytes32)
    {
        return prefixed(keccak256(abi.encodePacked(_code)));
    }

     /// builds a prefixed hash to mimic the behavior of eth_sign.
    function prefixed(bytes32 hash) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
    }

I run the signature in remix, both in virtual machine and with the metamask.
I never manage to validate any signature.
What am I doing wrong?

I still have the same problem. I can’t verify any signature. I don’t know what I am doing wrong. I create the hash with the shared functions and sign them through Remix. But I always get false using the above code.

you can test it separately with another tool to compute the hash and compare the hashes to see if they have the same value

You are absolutely right.
I have done the check by creating another function that checks signed hashes as I did in other contracts.
The function is:

function testingSignWithoutLibrary(
        bytes32 _hash,
        address _signer,
        bytes memory signature
    ) external view returns (bool) {
       // bytes32 message = prefixed(keccak256(abi.encodePacked(_idGame, _score, msg.sender)));

        require(recoverSigner(_hash, signature) == _signer, "its not the signer");
        return true;
    }

Then I created the hashes with the hash creation functions with prefixed and without, and I get false as well.

Now I am more puzzled than before.

I share the whole contract:


// SPDX-License-Identifier: MIT
import "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol";

pragma solidity ^0.8.0;


contract TestingSignatureChecker  {

       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));
    }


        function test(address signer, bytes32 hash, bytes memory signature) external view  returns (bool) {

        return isValidSignatureNow(signer,  hash,  signature);
    }

        function getMessageHash(string memory _code) public pure returns (bytes32)
    {
        return keccak256(abi.encodePacked(_code));
    }

       function getMessageHashWithPrefixed(string memory _code) public pure returns (bytes32)
    {
        return prefixed(keccak256(abi.encodePacked(_code)));
    }

     /// builds a prefixed hash to mimic the behavior of eth_sign.
    function prefixed(bytes32 hash) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
    }

      function testingSignWithoutLibrary(
        bytes32 _hash,
        address _signer,
        bytes memory signature
    ) external view returns (bool) {
       // bytes32 message = prefixed(keccak256(abi.encodePacked(_idGame, _score, msg.sender)));

        require(recoverSigner(_hash, signature) == _signer, "its no the signer");
        return true;
    }

     function recoverSigner(bytes32 message, bytes memory sig) internal pure returns (address) {
        (uint8 v, bytes32 r, bytes32 s) = splitSignature(sig);

        return ecrecover(message, v, r, s);
    }

    /// signature methods.
    function splitSignature(bytes memory sig)
        internal
        pure
        returns (
            uint8 v,
            bytes32 r,
            bytes32 s
        )
    {
        require(sig.length == 65);

        assembly {
            // first 32 bytes, after the length prefix.
            r := mload(add(sig, 32))
            // second 32 bytes.
            s := mload(add(sig, 64))
            // final byte (first byte of the next 32 bytes).
            v := byte(0, mload(add(sig, 96)))
        }

        return (v, r, s);
    }


}

@cryptokid,
do you think the problem is that I only use one value to create the hash? That’s why I can’t validate it?
As I said, I use the same code to validate a hash formed by several parameters and signed later. However, transferring the code to this example, it fails here and not on my platform.
I’m probably confused and I don’t see something fundamental.