pragma solidity >=0.4.22 <0.6.0; import "remix_tests.sol"; // this import is automatically injected by Remix. contract dapp { mapping (address => uint) public smiles; // 測試用 mapping (address => uint) public nonces; bytes32 public DOMAIN_SEPARATOR; constructor() public { DOMAIN_SEPARATOR = keccak256(abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes("dapp")), // contract name keccak256(bytes("0.1")), // contract version 1, // chain ID address(this) // contract address )); } function smile(address smiler) public { // 測試用 smiles[smiler] ++; } function metaSmile(address addr) public { // 測試用 bytes memory payload = abi.encodeWithSignature("smile(address)", addr); // "smile(address)" 正是 smile 的 function signature (bool success, bytes memory returnData) = address(this).call(payload); require(success); } function metaTx(address initiatorAddr, bytes calldata message, uint8 v, bytes32 r, bytes32 s, uint256 nonce) external returns (bool) { // *注意: (bytes4 functionSigEncoded, bytes memory paramPacked) = abi.decode(message, (bytes4, bytes)); bytes32 digest = keccak256( // 把 input argument 裡除簽名外全依 EIP712 規格打包 abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR, keccak256(abi.encode(initiatorAddr, message, nonce)) ) ); require( // 確認是 initiator 的簽名 initiatorAddr == ecrecover(digest, v, r, s), "dapp/ invalid metaTx" ); require( // 確認 nonce 正確,並更新 nonces nonce==nonces[initiatorAddr], "dapp/ incorrect nonce" ); nonces[initiatorAddr]++; // 用 low-level call 執行 message 內容 // *注意: 目前沒有檢查 message 內容 (bool success, bytes memory returnData) = address(this).call(message); require(success, "dapp/ metaTx execution failed"); return true; } }
0.6.0