EIP712 не возвращает адрес пользователя через Smart Contract (Solidity)
Пытаюсь подписать EIP-712 через фронт и декодировать через смарт контракт, передаю хэш подписи (V, R, S) и message в смарт контракт, но контракт возвращает совсем другой адрес. Не могу понять в чем проблема, кто сталкивался помогите пожалуйста :)
ФРОНТ:
let msgParams = JSON.stringify({ types: { EIP712Domain: [ { name: 'chainId', type: 'uint256' }, { name: 'name', type: 'string' }, { name: 'verifyingContract', type: 'address'}, { name: 'version', type: 'string' }, ], Person: [ { name: 'name', type: 'string'}, { name: 'wallets', type: 'address'}, ], Mail: [ { name: 'contents', type: 'string'}, { name: '_from', type: 'Person' }, { name: 'to', type: 'Person' }, ]}, primaryType: "Mail", domain: { chainId: 42, name: "Aibek, Hello!", verifyingContract: "0xDa2a0dE73e600fC111E1c324530000b739A68E1F", version: "1", }, message: { contents: "Aibek, Hello!", _from: { name: "Aibek", wallets: "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826"}, to: { name: "Timaaaaa", wallets: "0xfcb2b98856Aa507307748Ca0C6456F6BA7355ee9"} } }); let from = '0xAE49BF7b702D9F2BF533a82fDf31e70A17D39f76'; let params = [from, msgParams]; let method = 'eth_signTypedData_v4'; let vrsResult = window.ethereum.request({method, params, from})Cмарт контракт:
pragma solidity ^0.8.4; import '../.deps/npm/@openzeppelin/contracts/token/ERC20/IERC20.sol'; contract Сontract { mapping(address=>uint) private _balance; uint public counter; event Transfer(address indexed from, address indexed to, uint256 amount); event tokenInContract(address indexed from, uint256 amount); event hashDecode(address indexed from, address indexed hashDecode); struct EIP712Domain{ uint256 chainId; string name; address verifyingContract; string version; } struct Person{ string name; address wallets; } struct Mail{ string contents; Person _from; Person to; } bytes32 DOMAIN_SEPARATOR = hashDomain(EIP712Domain({ chainId: 42, name: "Aibek, Hello!", verifyingContract: 0xDa2a0dE73e600fC111E1c324530000b739A68E1F, version: "1" })); bytes32 private constant EIP712_DOMAIN_TYPEHASH = keccak256("EIP712Domain(uint256 chainId,string name, address verifyingContract,string version)"); bytes32 private constant PERSON_TYPEHASH = keccak256("Person(string name,address wallets)"); bytes32 private constant MESSAGE_TYPEHASH = keccak256("Mail(sting contents,Person _from,Person to)Person(string name,address wallets)"); function hashDomain(EIP712Domain memory eip712domain) private pure returns(bytes32){ return keccak256(abi.encode( EIP712_DOMAIN_TYPEHASH, eip712domain.chainId, keccak256(bytes(eip712domain.name)), eip712domain.verifyingContract, keccak256(bytes(eip712domain.version)))); } function hashData(Person memory data) private pure returns(bytes32){ return keccak256(abi.encode( PERSON_TYPEHASH, keccak256(bytes(data.name)), data.wallets )); } function hashMessage(Mail memory message) private view returns(bytes32){ return keccak256(abi.encode( MESSAGE_TYPEHASH, keccak256(bytes(message.contents)), hashData(message._from), hashData(message.to) )); } function hashAllTheMessage(Mail memory message) private view returns(bytes32){ return keccak256(abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR, hashMessage(message) )); } function hashCheck(Mail memory message, uint8 v, bytes32 r, bytes32 s) public returns(address){ address sender = ecrecover(hashAllTheMessage(message), v, r, s); emit hashDecode(msg.sender, sender); return sender; } function transferTokenToUser(Mail memory message, address erc20Address, uint amount, uint8 v, bytes32 r, bytes32 s) public payable returns(bool){ address decodeHash = hashCheck(message, v, r, s); require(msg.sender == decodeHash, 'PROTOCOL: DIFFERENT_ADDRESS'); require(amount >= msg.value, 'PROTOCOL: SENDING_TOKEN_NOT_EQUAL'); IERC20 sendToken = IERC20(erc20Address); sendToken.transfer(msg.sender, amount); _balance[msg.sender] -= amount; emit tokenInContract(msg.sender, amount); return true; } function acceptTokenToContract(address erc20Address, uint amount) public payable returns (bool){ IERC20 token = IERC20(erc20Address); require(token.balanceOf(msg.sender) >= amount, "PROTOCOL: BALANCE_INSUFFICIENT"); require(token.allowance(msg.sender, address(this)) >= amount, "PROTOCOL: AMOUNT_NOT_ALLOWED"); token.transferFrom(msg.sender, address(this), amount); _balance[msg.sender] += amount; emit Transfer(msg.sender, address(this), amount); return true; } function testVerify() public payable returns (bool) { Mail memory mails = Mail({contents:"Aibek, Hello!", _from: Person({name:"Aibek", wallets:0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826 }), to: Person({name:"Timaaaaa", wallets:0xfcb2b98856Aa507307748Ca0C6456F6BA7355ee9 }) }); bytes32 s = 0x558b1c363e2e88697eb5496295b5e27681d051cc7350676033c43bddbce6998c; bytes32 r = 0x1386bc67d8775ba0d6c6b5065dfc17d61ab86ce7fa765b7e861e99bae6c85a6a; uint8 v = 28; address signerAddr = 0xAE49BF7b702D9F2BF533a82fDf31e70A17D39f76; return signerAddr == hashCheck(mails, v, r, s); }}