mirror of
https://github.com/status-im/EIPs.git
synced 2025-01-11 07:15:58 +00:00
d686a655de
* Add eip-signTypedData * Change namespace from personal to eth * Change a way schema hash is combined together with data as proposed by @MicahZoltu * Add a note about it being implemented in MetaMask as an experimental feature * Add signerAddress as a parameter * Add test vectors * Fix an example * Missing commas, periods * Address the feedback * Add a missing signerAddress parameter in the example * Change the order of parameters to have an address as a second arg * Wrote motivation * WIP * First draft of specification * Fixes * Update to new EIP format * Assign EIP number * Clarify encoding of short static byte arrays * Removed Solidity changes * Fixup * Fix typos * WIP EIP191 * WIP TODO * WIP Replay attacks * Fixes the sorted by name example encoding * Remove Solidity hash * Added note on replay protection * Redesign domain separator * Include images and simple motivation * Fix up EIP metadata formatting * Add domain separator * Remove replay attacks from todo list * Add Jacob Evans to authors * Clarify encodeData * Rename Message example to Mail * Update mock signing screen * Rework EIP712Domain * Update Solidity example * Update Javascript example * Relocate files * Rename DomainSeparator to EIP712Domain (fix) * Move examples to separate files * Remove httpOrigin domain parameter * Update JSON-Schema * Add registery of version bytes * Add eip712 to eip191 registery * Add requires header * Set correct language on all snipets * GitHub highlighting for Solidity files * Update Web3 API specification * Use abi.encode where possible * Update JSON-RPC specification * Asset path repo is ethereums * Correctly spelling of registry
107 lines
3.1 KiB
Solidity
107 lines
3.1 KiB
Solidity
pragma solidity ^0.4.24;
|
|
|
|
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;
|
|
}
|
|
}
|