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?