Skip to content

Instantly share code, notes, and snippets.

@leon-do
Last active May 17, 2023 19:09
Show Gist options
  • Save leon-do/547a79dc7582a30145f075c44696ce28 to your computer and use it in GitHub Desktop.
Save leon-do/547a79dc7582a30145f075c44696ce28 to your computer and use it in GitHub Desktop.
EIP712 WROSE
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
contract VerifyTypedData {
using ECDSA for bytes32;
/*
* @param _signature = 0xb066103c3fe76389334e2df744caa60d61b2e52f57ea1c3569941558ae8a43a03312ed2e3326bcbea6af812cb50e0e1c8fad12bdfdde60f9459b634674c86dbc1b
* @parm _to = 0xdD4c825203f97984e7867F11eeCc813A036089D1
* @param _value = 123
* @param _nonce = 1
* @return address = 0xdD4c825203f97984e7867F11eeCc813A036089D1
*/
function getSigner(bytes memory _signature, address _to,uint256 _value,uint256 _nonce,uint256 _reward)
public
view
returns (address)
{
// EIP721 domain type
string memory name = "WROSE";
string memory version = "1";
uint256 chainId = 42262;
address verifyingContract = address(this); // 0x0000000000000000000000000000000000000000;
// stringified types
string memory EIP712_DOMAIN_TYPE = "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)";
string memory MESSAGE_TYPE = "Message(address to,uint256 value,uint256 nonce,uint256 reward)";
// hash to prevent signature collision
bytes32 DOMAIN_SEPARATOR = keccak256(
abi.encode(
keccak256(abi.encodePacked(EIP712_DOMAIN_TYPE)),
keccak256(abi.encodePacked(name)),
keccak256(abi.encodePacked(version)),
chainId,
verifyingContract
)
);
// hash typed data
bytes32 hash = keccak256(
abi.encodePacked(
"\x19\x01", // backslash is needed to escape the character
DOMAIN_SEPARATOR,
keccak256(
abi.encode(
keccak256(abi.encodePacked(MESSAGE_TYPE)),
_to,_value,_nonce,_reward // _myValue
)
)
)
);
return hash.recover(_signature);
}
}
/**
<script>
// https://docs.metamask.io/guide/signing-data.html#sign-typed-data-v4
(async function () {
// connect to wallet
const from = await ethereum.request({ method: "eth_requestAccounts" });
const msgParams = JSON.stringify({
domain: {
// Give a user friendly name to the specific contract you are signing for.
name: "WROSE", // "MyName"
// Just let's you know the latest version. Definitely make sure the field name is correct.
version: "1", // "1"
// Defining the chain aka Rinkeby testnet or Ethereum Main Net
chainId: 42262, // 1
// If name isn't enough add verifying contract to make sure you are establishing contracts with the proper entity
verifyingContract: "0x0000000000000000000000000000000000000000"// "0x0000000000000000000000000000000000000000",
},
// Defining the message signing data content.
message: {
to: "0xdD4c825203f97984e7867F11eeCc813A036089D1",value: 123,nonce: 1,reward: 123123,
},
// Refers to the keys of the *types* object below.
primaryType: "Message",
types: {
EIP712Domain: [
{ name: "name", type: "string" },
{ name: "version", type: "string" },
{ name: "chainId", type: "uint256" },
{ name: "verifyingContract", type: "address" },
],
// Refer to primaryType
Message: [{"name":"to","type":"address"},{"name":"value","type":"uint256"},{"name":"nonce","type":"uint256"},{"name":"reward","type":"uint256"}] // [{ name: "myValue", type: "uint256" }],
},
});
web3.currentProvider.sendAsync(
{
method: "eth_signTypedData_v4",
params: [from[0], msgParams],
from: from[0],
},
function (err, result) {
if (err) return console.dir(err);
if (result.error) {
alert(result.error.message);
}
if (result.error) return console.error("ERROR", result);
console.log("SIGNATURE:" + JSON.stringify(result.result));
}
);
})()
</script>
**/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment