eip712 ====== Generates Solidity code to verify [EIP-712] style signatures. ## Usage First, create an abstract contract implementing the functionality you want: ```solidity // SPDX-License-Identifier: CC0-1.0 pragma solidity ^0.8.11; abstract contract NameRegistry { mapping (string => address) public nameToAddress; mapping (address => string) public addressToName; // This `claim` function implements the functionality you want to expose // via an EIP-712 signature. // // Importantly, the first argument must be the sender's address, and // the function must be internal. function claim(address sender, string memory name) internal { require(bytes(addressToName[sender]).length == 0, "address already registered"); require(nameToAddress[name] == address(0), "name already registered"); addressToName[sender] = name; nameToAddress[name] = sender; } // You can optionally expose your functionality using `msg.sender`. function claim(string memory name) external { claim(msg.sender, name); } // Finally, you should declare an abstract function that accepts a signature. // // The implementation will be generated for you. function claim(string memory name, uint8 v, bytes32 r, bytes32 s) external virtual; } ``` ### On the Command Line Install `eip712-cli`: ```bash $ cargo install eip712-cli ``` Then run it with: ```bash $ eip712 \ --base NameRegistry \ --signing-domain NameRegistry \ --version 1 \ --output /tmp/output.sol \ NameRegistry.json ``` ### As a Library For advanced uses, this crate can be used as a library from Rust or JavaScript. #### Rust ```rust use eip712::Eip712; use std::io::Write; fn main() { // Read the ABI file (normally generated by `solc`.) let abi = include_str!("NameRegistry.json"); let mut output = String::new(); // Configure and run the generator. Eip712::<()>::new("NameRegistry") // Name of the base contract. .signing_domain("NameRegistry") // Name for the EIP-712 domain. .version("1") // Contract version. .read_str(abi) .unwrap() .generate(&mut output) .unwrap(); std::io::stdout().write_all(output.as_bytes()).unwrap(); } ``` #### JavaScript ```javascript import { default as eip712, Eip712 } from './eip712.js'; async function main() { await eip712(); // Read the ABI file (normally generated by `solc`.) const resp = await fetch("./NameRegistry.json"); const abi = await resp.text(); // Configure and run the generator. const output = new Eip712("NameRegistry") // Name of the base contract. .error(console.log) // Error handler. .warning(console.log) // Warning handler. .signing_domain("NameRegistry") // Name for the EIP-712 domain. .version("1") // Contract version. .read_str(abi) .generate(); let elem = document.createElement('pre'); elem.innerText = output; document.body.appendChild(elem); } main(); ``` [EIP-712]: https://eips.ethereum.org/EIPS/eip-712