eth-erc712

ERC712 typed data sign material builder
Log | Files | Refs

commit 5af30d5955be0ae8be0ddbcc5a1d0043a45f6dc5
Author: lash <dev@holbrook.no>
Date:   Tue, 28 Mar 2023 10:15:02 +0100

Initial commit

Diffstat:
Asolidity/Example.sol | 109+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 109 insertions(+), 0 deletions(-)

diff --git a/solidity/Example.sol b/solidity/Example.sol @@ -0,0 +1,109 @@ +pragma solidity ^0.4.24; + +// This file was copied from https://eips.ethereum.org/assets/eip-712/Example.sol +// SPDX-License-Identifier: CC0-1.0 + +contract Example { + + struct EIP712Domain { + string name; + string version; + uint256 chainId; + address verifyingContract; + } + + struct Person { + string name; + address wallet; + } + + struct Mail { + Person from; + Person to; + string contents; + } + + bytes32 constant EIP712DOMAIN_TYPEHASH = keccak256( + "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" + ); + + bytes32 constant PERSON_TYPEHASH = keccak256( + "Person(string name,address wallet)" + ); + + bytes32 constant MAIL_TYPEHASH = keccak256( + "Mail(Person from,Person to,string contents)Person(string name,address wallet)" + ); + + bytes32 DOMAIN_SEPARATOR; + + constructor () public { + DOMAIN_SEPARATOR = hash(EIP712Domain({ + name: "Ether Mail", + version: '1', + chainId: 1, + // verifyingContract: this + verifyingContract: 0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC + })); + } + + function hash(EIP712Domain eip712Domain) internal pure returns (bytes32) { + return keccak256(abi.encode( + EIP712DOMAIN_TYPEHASH, + keccak256(bytes(eip712Domain.name)), + keccak256(bytes(eip712Domain.version)), + eip712Domain.chainId, + eip712Domain.verifyingContract + )); + } + + function hash(Person person) internal pure returns (bytes32) { + return keccak256(abi.encode( + PERSON_TYPEHASH, + keccak256(bytes(person.name)), + person.wallet + )); + } + + function hash(Mail mail) internal pure returns (bytes32) { + return keccak256(abi.encode( + MAIL_TYPEHASH, + hash(mail.from), + hash(mail.to), + keccak256(bytes(mail.contents)) + )); + } + + function verify(Mail mail, uint8 v, bytes32 r, bytes32 s) internal view returns (bool) { + // Note: we need to use `encodePacked` here instead of `encode`. + bytes32 digest = keccak256(abi.encodePacked( + "\x19\x01", + DOMAIN_SEPARATOR, + hash(mail) + )); + return ecrecover(digest, v, r, s) == mail.from.wallet; + } + + function test() public view returns (bool) { + // Example signed message + Mail memory mail = Mail({ + from: Person({ + name: "Cow", + wallet: 0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826 + }), + to: Person({ + name: "Bob", + wallet: 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB + }), + contents: "Hello, Bob!" + }); + uint8 v = 28; + bytes32 r = 0x4355c47d63924e8a72e509b65029052eb6c299d53a04e167c5775fd466751c9d; + bytes32 s = 0x07299936d304c153f6443dfa05f40ff007d72911b6f72307f996231605b91562; + + assert(DOMAIN_SEPARATOR == 0xf2cee375fa42b42143804025fc449deafd50cc031ca257e0b194a650a912090f); + assert(hash(mail) == 0xc52c0ee5d84264471806290a3f2c4cecfc5490626bf912d01f240d7a274b371e); + assert(verify(mail, v, r, s)); + return true; + } +}