github.com/status-im/status-go@v1.1.0/services/typeddata/eip712example/example.sol (about)

     1  pragma solidity ^0.8.0;
     2  
     3  contract Example {
     4  
     5      struct EIP712Domain {
     6          string  name;
     7          string  version;
     8          uint256 chainId;
     9          address verifyingContract;
    10      }
    11  
    12      struct Person {
    13          string name;
    14          address wallet;
    15      }
    16  
    17      struct Mail {
    18          Person from;
    19          Person to;
    20          string contents;
    21      }
    22  
    23      bytes32 constant EIP712DOMAIN_TYPEHASH = keccak256(
    24          "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
    25      );
    26  
    27      bytes32 constant PERSON_TYPEHASH = keccak256(
    28          "Person(string name,address wallet)"
    29      );
    30  
    31      bytes32 constant MAIL_TYPEHASH = keccak256(
    32          "Mail(Person from,Person to,string contents)Person(string name,address wallet)"
    33      );
    34  
    35      Mail internal mail = Mail({
    36              from: Person({
    37                 name: "Cow",
    38                 wallet: 0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826
    39              }),
    40              to: Person({
    41                  name: "Bob",
    42                  wallet: 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB
    43              }),
    44              contents: "Hello, Bob!"
    45      });
    46  
    47      bytes32 public DOMAIN_SEPARATOR;
    48      bytes32 public MAIL;
    49  
    50      constructor () public {
    51          DOMAIN_SEPARATOR = hash(EIP712Domain({
    52              name: "Ether Mail",
    53              version: '1',
    54              chainId: 1,
    55              // verifyingContract: this
    56              verifyingContract: 0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC
    57          }));
    58          MAIL = hash(mail);
    59      }
    60  
    61      function hash(EIP712Domain memory eip712Domain) internal pure returns (bytes32) {
    62          return keccak256(abi.encode(
    63              EIP712DOMAIN_TYPEHASH,
    64              keccak256(bytes(eip712Domain.name)),
    65              keccak256(bytes(eip712Domain.version)),
    66              eip712Domain.chainId,
    67              eip712Domain.verifyingContract
    68          ));
    69      }
    70  
    71      function hash(Person memory person) internal pure returns (bytes32) {
    72          return keccak256(abi.encode(
    73              PERSON_TYPEHASH,
    74              keccak256(bytes(person.name)),
    75              person.wallet
    76          ));
    77      }
    78  
    79      function hash(Mail memory m) internal pure returns (bytes32) {
    80          return keccak256(abi.encode(
    81              MAIL_TYPEHASH,
    82              hash(m.from),
    83              hash(m.to),
    84              keccak256(bytes(m.contents))
    85          ));
    86      }
    87  
    88      function verify(uint8 v, bytes32 r, bytes32 s) public returns (bool) {
    89          // Note: we need to use `encodePacked` here instead of `encode`.
    90          bytes32 digest = keccak256(abi.encodePacked(
    91              "\x19\x01",
    92              DOMAIN_SEPARATOR,
    93              hash(mail)
    94          ));
    95          require(ecrecover(digest, v, r, s) == msg.sender);
    96          return true;
    97      }
    98  }