Skip to content

Instantly share code, notes, and snippets.

@Ankarrr
Created January 22, 2020 08:45
Show Gist options
  • Save Ankarrr/6d14a2f73dd12cf889130946f0ef1629 to your computer and use it in GitHub Desktop.
Save Ankarrr/6d14a2f73dd12cf889130946f0ef1629 to your computer and use it in GitHub Desktop.
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