Created
          January 22, 2020 08:45 
        
      - 
      
- 
        Save Ankarrr/6d14a2f73dd12cf889130946f0ef1629 to your computer and use it in GitHub Desktop. 
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | 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; | |
| } | |
| } | 
  
    Sign up for free
    to join this conversation on GitHub.
    Already have an account?
    Sign in to comment