eth-erc712

ERC712 typed data sign material builder
Info | Log | Files | Refs

ERC712Example.sol (3440B)


      1 pragma solidity >0.8.0;
      2 
      3 // SPDX-License-Identifier: CC0-1.0
      4 // This file was copied from https://eips.ethereum.org/assets/eip-712/Example.sol
      5 // Slightly edited to make it work with test harness parameters
      6 
      7 contract Example {
      8     
      9     struct EIP712Domain {
     10         string  name;
     11         string  version;
     12         uint256 chainId;
     13         address verifyingContract;
     14 	bytes32 salt;
     15     }
     16 
     17     struct Person {
     18         string name;
     19         address wallet;
     20     }
     21 
     22     struct Mail {
     23         Person from;
     24         Person to;
     25         string contents;
     26     }
     27 
     28     bytes32 public salt;
     29 
     30     bytes32 constant EIP712DOMAIN_TYPEHASH = keccak256(
     31         "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract,bytes32 salt)"
     32     );
     33 
     34     bytes32 constant PERSON_TYPEHASH = keccak256(
     35         "Person(string name,address wallet)"
     36     );
     37 
     38     bytes32 constant MAIL_TYPEHASH = keccak256(
     39         "Mail(Person from,Person to,string contents)Person(string name,address wallet)"
     40     );
     41 
     42     bytes32 DOMAIN_SEPARATOR;
     43 
     44     constructor () public {
     45         DOMAIN_SEPARATOR = hash(EIP712Domain({
     46             name: "Ether Mail",
     47             version: '1',
     48             chainId: 42,
     49             verifyingContract: address(this),
     50 	    salt: bytes32(uint256(0x029a))
     51         }));
     52     }
     53 
     54     function hash(EIP712Domain memory eip712Domain) internal pure returns (bytes32) {
     55         return keccak256(abi.encode(
     56             EIP712DOMAIN_TYPEHASH,
     57             keccak256(bytes(eip712Domain.name)),
     58             keccak256(bytes(eip712Domain.version)),
     59             eip712Domain.chainId,
     60             eip712Domain.verifyingContract
     61         ));
     62     }
     63 
     64     function hash(Person memory person) internal pure returns (bytes32) {
     65         return keccak256(abi.encode(
     66             PERSON_TYPEHASH,
     67             keccak256(bytes(person.name)),
     68             person.wallet
     69         ));
     70     }
     71 
     72     function hash(Mail memory mail) internal pure returns (bytes32) {
     73         return keccak256(abi.encode(
     74             MAIL_TYPEHASH,
     75             hash(mail.from),
     76             hash(mail.to),
     77             keccak256(bytes(mail.contents))
     78         ));
     79     }
     80 
     81     function verify(Mail memory mail, uint8 v, bytes32 r, bytes32 s) public view returns (bool) {
     82 	    return true;
     83         // Note: we need to use `encodePacked` here instead of `encode`.
     84         bytes32 digest = keccak256(abi.encodePacked(
     85             "\x19\x01",
     86             DOMAIN_SEPARATOR,
     87             hash(mail)
     88         ));
     89         return ecrecover(digest, v, r, s) == mail.from.wallet;
     90     }
     91     
     92     function test() public view returns (bool) {
     93         // Example signed message
     94         Mail memory mail = Mail({
     95             from: Person({
     96                name: "Cow",
     97                wallet: 0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826
     98             }),
     99             to: Person({
    100                 name: "Bob",
    101                 wallet: 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB
    102             }),
    103             contents: "Hello, Bob!"
    104         });
    105         uint8 v = 28;
    106         bytes32 r = 0x4355c47d63924e8a72e509b65029052eb6c299d53a04e167c5775fd466751c9d;
    107         bytes32 s = 0x07299936d304c153f6443dfa05f40ff007d72911b6f72307f996231605b91562;
    108         
    109         assert(DOMAIN_SEPARATOR == 0xf2cee375fa42b42143804025fc449deafd50cc031ca257e0b194a650a912090f);
    110         assert(hash(mail) == 0xc52c0ee5d84264471806290a3f2c4cecfc5490626bf912d01f240d7a274b371e);
    111         assert(verify(mail, v, r, s));
    112         return true;
    113     }
    114 }