pragma experimental ABIEncoderV2; pragma solidity ^0.5.0; contract Verifier { bytes32 constant SALT = 0xf2d857f4a3edcb9b78b4d503bfe733db1e3f6cdc2b7971ee739626c97e86a558; // Finally method to identify Dapp uint256 chainId = 3; // Ropsten testnet string private constant EIP712_DOMAIN = "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract,bytes32 salt)"; bytes32 private constant EIP712_DOMAIN_TYPEHASH = keccak256(abi.encodePacked(EIP712_DOMAIN)); bytes32 private DOMAIN_SEPARATOR = keccak256(abi.encode( EIP712_DOMAIN_TYPEHASH, keccak256("EIP712Dapp"), keccak256("1"), chainId, address(this), SALT )); mapping (address => uint) public smiles; string public constant SMILE_METHOD_SIG = 'smile(address,uint256)'; bytes4 public constant SMILE_METHOD_IDENTIFIER = bytes4(keccak256(bytes(SMILE_METHOD_SIG))); bytes32 public constant SMILE_METHOD_SIG_HASH = keccak256(abi.encodePacked(SMILE_METHOD_SIG)); // for debug // [{ name: "method_name", type: "string"}, // { name: "smiler", type: "address"}, // { name: "smile_num", type: "uint256" }, // { name: "method_identifier", type: "bytes4" }, // { name: "params_packed", type: "bytes" } ]; string private constant SMILE_TYPE = "Packet(string method_name,address smiler,uint256 smile_num,bytes4 method_identifier,bytes params_packed)"; bytes32 private constant SMILE_TYPEHASH = keccak256(abi.encodePacked(SMILE_TYPE)); mapping (address => uint) public nods; string public constant NOD_METHOD_SIG = 'nod(address,uint256,uint256)'; bytes4 public constant NOD_METHOD_IDENTIFIER = bytes4(keccak256(bytes(NOD_METHOD_SIG))); bytes32 public constant NOD_METHOD_SIG_HASH = keccak256(abi.encodePacked(NOD_METHOD_SIG)); // for debug // [{ name: "method_name", type: "string"}, // { name: "nodder", type: "address"}, // { name: "nod_num", type: "uint256" }, // { name: "nod_mult", type: "uint256" }, // { name: "method_identifier", type: "bytes4" }, // { name: "params_packed", type: "bytes" } ]; string private constant NOD_TYPE = "Packet(string method_name,address nodder,uint256 nod_num,uint256 nod_mult,bytes4 method_identifier,bytes params_packed)"; bytes32 private constant NOD_TYPEHASH = keccak256(abi.encodePacked(NOD_TYPE)); bytes4 public lastMethod; // for debug bytes public lastParams; // for debug bytes32 public lastParamsHash; // for debug //////////////////////////////////////////////////////////// function nod(address nodder, uint nodNum, uint nodMultiplier) public { nods[nodder] = nods[nodder]*nodMultiplier + nodNum; } function smile(address smiler, uint256 smileNum) public { smiles[smiler] += smileNum; } /////////////////////////////// function verifyMeta(address signer, bytes4 method, bytes memory params, bytes32 r, bytes32 s, uint8 v) public returns (bool) { require( (method == SMILE_METHOD_IDENTIFIER) || (method == NOD_METHOD_IDENTIFIER) ); if (method == SMILE_METHOD_IDENTIFIER) { (address addr, uint256 x) = abi.decode(params, (address, uint256)); bytes32 digest = keccak256(abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR, keccak256(abi.encode( SMILE_TYPEHASH, keccak256(bytes(SMILE_METHOD_SIG)), // * EIP712: strings are encoded as its hash; bytes() works but abi.encodePacked doesn't addr, x, method, keccak256(params) // * EIP712: bytes are encoded as its hash )) )); require(signer == ecrecover(digest, v, r, s)); // TODO: 驗證 nonce,但是注意 metamask 在 Gitcoin 上說: // "This method may make use of a nonce, but for some use cases, // allowing these messages to be submitted in any order may be an advantage, // and so another replay-protection measure may be preferable." smile(addr, x); } else if (method == NOD_METHOD_IDENTIFIER) { (address addr, uint256 x, uint256 m) = abi.decode(params, (address, uint256, uint256)); bytes32 digest = keccak256(abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR, keccak256(abi.encode( NOD_TYPEHASH, keccak256(bytes(NOD_METHOD_SIG)), // * EIP712: strings are encoded as its hash; bytes() works but abi.encodePacked doesn't addr, x, m, method, keccak256(params) // * EIP712: bytes are encoded as its hash )) )); require(signer == ecrecover(digest, v, r, s)); // TODO: 驗證 nonce,但是注意 metamask 在 Gitcoin 上說: // "This method may make use of a nonce, but for some use cases, // allowing these messages to be submitted in any order may be an advantage, // and so another replay-protection measure may be preferable." nod(addr, x, m); } lastMethod = method; // for debug lastParams = params; // for debug lastParamsHash = keccak256(params); // for debug return true; } }
0.6.0