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; struct Smile { uint256 num; } string private constant SMILE_TYPE = "Smile(uint256 num)"; bytes32 private constant SMILE_TYPEHASH = keccak256(abi.encodePacked(SMILE_TYPE)); struct Packet { bytes4 method; bytes params; } string private constant PACKET_TYPE = "Packet(bytes4 method,bytes params)"; bytes32 private constant PACKET_TYPEHASH = keccak256(abi.encodePacked(PACKET_TYPE)); bytes4 public lastMethod; // for debug bytes public lastParams; // for debug bytes32 public lastParamsHash; // for debug //////////////////////////////////////////////////////////// function smile(address smiler, uint256 smileNum) public { smiles[smiler] += smileNum; } function hashSmile(uint256 smileNum) private view returns (bytes32){ return keccak256(abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR, keccak256(abi.encode( SMILE_TYPEHASH, smileNum )) )); } function verifySmile(address signer, uint256 smileNum, bytes32 r, bytes32 s, uint8 v) public returns (bool) { // TODO: 檢查 nonce // TODO: 呼叫任意合約及傳入任意參數 require(signer == ecrecover(hashSmile(smileNum), v, r, s)); smile(signer, smileNum); return true; } /////////////////////////////// function hashMeta(bytes4 method, bytes memory params) private view returns (bytes32){ return keccak256(abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR, keccak256(abi.encode( PACKET_TYPEHASH, method, keccak256(params) // *** EIP712: bytes are encoded as its hash *** // Quote from EIP712: The dynamic values bytes and string are encoded as a keccak256 hash of their contents. )) )); } function verifyMeta(address signer, bytes4 method, bytes memory params, bytes32 r, bytes32 s, uint8 v) public returns (bool) { require(signer == ecrecover(hashMeta(method, params), v, r, s)); lastMethod = method; lastParams = params; lastParamsHash = keccak256(params); // TODO: 比對 method, 打開 params, 呼叫 method //(uint256 x, bool y) = abi.decode(params, (uint256, bool)); //smile(signer, x); return true; } }
0.6.0