GSNRecipientSignature.sol 2.4 KB

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