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 }