GSNRecipientSignature.sol 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. pragma solidity ^0.6.0;
  2. import "./GSNRecipient.sol";
  3. import "../cryptography/ECDSA.sol";
  4. /**
  5. * @dev A xref:ROOT:gsn-strategies.adoc#gsn-strategies[GSN strategy] that allows relayed transactions through when they are
  6. * accompanied by the signature of a trusted signer. The intent is for this signature to be generated by a server that
  7. * performs validations off-chain. Note that nothing is charged to the user in this scheme. Thus, the server should make
  8. * sure to account for this in their economic and threat model.
  9. */
  10. contract GSNRecipientSignature is GSNRecipient {
  11. using ECDSA for bytes32;
  12. address private _trustedSigner;
  13. enum GSNRecipientSignatureErrorCodes {
  14. INVALID_SIGNER
  15. }
  16. /**
  17. * @dev Sets the trusted signer that is going to be producing signatures to approve relayed calls.
  18. */
  19. constructor(address trustedSigner) public {
  20. require(trustedSigner != address(0), "GSNRecipientSignature: trusted signer is the zero address");
  21. _trustedSigner = trustedSigner;
  22. }
  23. /**
  24. * @dev Ensures that only transactions with a trusted signature can be relayed through the GSN.
  25. */
  26. function acceptRelayedCall(
  27. address relay,
  28. address from,
  29. bytes calldata encodedFunction,
  30. uint256 transactionFee,
  31. uint256 gasPrice,
  32. uint256 gasLimit,
  33. uint256 nonce,
  34. bytes calldata approvalData,
  35. uint256
  36. )
  37. external
  38. view
  39. virtual
  40. override
  41. returns (uint256, bytes memory)
  42. {
  43. bytes memory blob = abi.encodePacked(
  44. relay,
  45. from,
  46. encodedFunction,
  47. transactionFee,
  48. gasPrice,
  49. gasLimit,
  50. nonce, // Prevents replays on RelayHub
  51. getHubAddr(), // Prevents replays in multiple RelayHubs
  52. address(this) // Prevents replays in multiple recipients
  53. );
  54. if (keccak256(blob).toEthSignedMessageHash().recover(approvalData) == _trustedSigner) {
  55. return _approveRelayedCall();
  56. } else {
  57. return _rejectRelayedCall(uint256(GSNRecipientSignatureErrorCodes.INVALID_SIGNER));
  58. }
  59. }
  60. function _preRelayedCall(bytes memory) internal virtual override returns (bytes32) { }
  61. function _postRelayedCall(bytes memory, bool, uint256, bytes32) internal virtual override { }
  62. }