IRelayHub.sol 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. // SPDX-License-Identifier: MIT
  2. pragma solidity ^0.6.0;
  3. /**
  4. * @dev Interface for `RelayHub`, the core contract of the GSN. Users should not need to interact with this contract
  5. * directly.
  6. *
  7. * See the https://github.com/OpenZeppelin/openzeppelin-gsn-helpers[OpenZeppelin GSN helpers] for more information on
  8. * how to deploy an instance of `RelayHub` on your local test network.
  9. */
  10. interface IRelayHub {
  11. // Relay management
  12. /**
  13. * @dev Adds stake to a relay and sets its `unstakeDelay`. If the relay does not exist, it is created, and the caller
  14. * of this function becomes its owner. If the relay already exists, only the owner can call this function. A relay
  15. * cannot be its own owner.
  16. *
  17. * All Ether in this function call will be added to the relay's stake.
  18. * Its unstake delay will be assigned to `unstakeDelay`, but the new value must be greater or equal to the current one.
  19. *
  20. * Emits a {Staked} event.
  21. */
  22. function stake(address relayaddr, uint256 unstakeDelay) external payable;
  23. /**
  24. * @dev Emitted when a relay's stake or unstakeDelay are increased
  25. */
  26. event Staked(address indexed relay, uint256 stake, uint256 unstakeDelay);
  27. /**
  28. * @dev Registers the caller as a relay.
  29. * The relay must be staked for, and not be a contract (i.e. this function must be called directly from an EOA).
  30. *
  31. * This function can be called multiple times, emitting new {RelayAdded} events. Note that the received
  32. * `transactionFee` is not enforced by {relayCall}.
  33. *
  34. * Emits a {RelayAdded} event.
  35. */
  36. function registerRelay(uint256 transactionFee, string calldata url) external;
  37. /**
  38. * @dev Emitted when a relay is registered or re-registered. Looking at these events (and filtering out
  39. * {RelayRemoved} events) lets a client discover the list of available relays.
  40. */
  41. event RelayAdded(address indexed relay, address indexed owner, uint256 transactionFee, uint256 stake, uint256 unstakeDelay, string url);
  42. /**
  43. * @dev Removes (deregisters) a relay. Unregistered (but staked for) relays can also be removed.
  44. *
  45. * Can only be called by the owner of the relay. After the relay's `unstakeDelay` has elapsed, {unstake} will be
  46. * callable.
  47. *
  48. * Emits a {RelayRemoved} event.
  49. */
  50. function removeRelayByOwner(address relay) external;
  51. /**
  52. * @dev Emitted when a relay is removed (deregistered). `unstakeTime` is the time when unstake will be callable.
  53. */
  54. event RelayRemoved(address indexed relay, uint256 unstakeTime);
  55. /** Deletes the relay from the system, and gives back its stake to the owner.
  56. *
  57. * Can only be called by the relay owner, after `unstakeDelay` has elapsed since {removeRelayByOwner} was called.
  58. *
  59. * Emits an {Unstaked} event.
  60. */
  61. function unstake(address relay) external;
  62. /**
  63. * @dev Emitted when a relay is unstaked for, including the returned stake.
  64. */
  65. event Unstaked(address indexed relay, uint256 stake);
  66. // States a relay can be in
  67. enum RelayState {
  68. Unknown, // The relay is unknown to the system: it has never been staked for
  69. Staked, // The relay has been staked for, but it is not yet active
  70. Registered, // The relay has registered itself, and is active (can relay calls)
  71. Removed // The relay has been removed by its owner and can no longer relay calls. It must wait for its unstakeDelay to elapse before it can unstake
  72. }
  73. /**
  74. * @dev Returns a relay's status. Note that relays can be deleted when unstaked or penalized, causing this function
  75. * to return an empty entry.
  76. */
  77. function getRelay(address relay) external view returns (uint256 totalStake, uint256 unstakeDelay, uint256 unstakeTime, address payable owner, RelayState state);
  78. // Balance management
  79. /**
  80. * @dev Deposits Ether for a contract, so that it can receive (and pay for) relayed transactions.
  81. *
  82. * Unused balance can only be withdrawn by the contract itself, by calling {withdraw}.
  83. *
  84. * Emits a {Deposited} event.
  85. */
  86. function depositFor(address target) external payable;
  87. /**
  88. * @dev Emitted when {depositFor} is called, including the amount and account that was funded.
  89. */
  90. event Deposited(address indexed recipient, address indexed from, uint256 amount);
  91. /**
  92. * @dev Returns an account's deposits. These can be either a contract's funds, or a relay owner's revenue.
  93. */
  94. function balanceOf(address target) external view returns (uint256);
  95. /**
  96. * Withdraws from an account's balance, sending it back to it. Relay owners call this to retrieve their revenue, and
  97. * contracts can use it to reduce their funding.
  98. *
  99. * Emits a {Withdrawn} event.
  100. */
  101. function withdraw(uint256 amount, address payable dest) external;
  102. /**
  103. * @dev Emitted when an account withdraws funds from `RelayHub`.
  104. */
  105. event Withdrawn(address indexed account, address indexed dest, uint256 amount);
  106. // Relaying
  107. /**
  108. * @dev Checks if the `RelayHub` will accept a relayed operation.
  109. * Multiple things must be true for this to happen:
  110. * - all arguments must be signed for by the sender (`from`)
  111. * - the sender's nonce must be the current one
  112. * - the recipient must accept this transaction (via {acceptRelayedCall})
  113. *
  114. * Returns a `PreconditionCheck` value (`OK` when the transaction can be relayed), or a recipient-specific error
  115. * code if it returns one in {acceptRelayedCall}.
  116. */
  117. function canRelay(
  118. address relay,
  119. address from,
  120. address to,
  121. bytes calldata encodedFunction,
  122. uint256 transactionFee,
  123. uint256 gasPrice,
  124. uint256 gasLimit,
  125. uint256 nonce,
  126. bytes calldata signature,
  127. bytes calldata approvalData
  128. ) external view returns (uint256 status, bytes memory recipientContext);
  129. // Preconditions for relaying, checked by canRelay and returned as the corresponding numeric values.
  130. enum PreconditionCheck {
  131. OK, // All checks passed, the call can be relayed
  132. WrongSignature, // The transaction to relay is not signed by requested sender
  133. WrongNonce, // The provided nonce has already been used by the sender
  134. AcceptRelayedCallReverted, // The recipient rejected this call via acceptRelayedCall
  135. InvalidRecipientStatusCode // The recipient returned an invalid (reserved) status code
  136. }
  137. /**
  138. * @dev Relays a transaction.
  139. *
  140. * For this to succeed, multiple conditions must be met:
  141. * - {canRelay} must `return PreconditionCheck.OK`
  142. * - the sender must be a registered relay
  143. * - the transaction's gas price must be larger or equal to the one that was requested by the sender
  144. * - the transaction must have enough gas to not run out of gas if all internal transactions (calls to the
  145. * recipient) use all gas available to them
  146. * - the recipient must have enough balance to pay the relay for the worst-case scenario (i.e. when all gas is
  147. * spent)
  148. *
  149. * If all conditions are met, the call will be relayed and the recipient charged. {preRelayedCall}, the encoded
  150. * function and {postRelayedCall} will be called in that order.
  151. *
  152. * Parameters:
  153. * - `from`: the client originating the request
  154. * - `to`: the target {IRelayRecipient} contract
  155. * - `encodedFunction`: the function call to relay, including data
  156. * - `transactionFee`: fee (%) the relay takes over actual gas cost
  157. * - `gasPrice`: gas price the client is willing to pay
  158. * - `gasLimit`: gas to forward when calling the encoded function
  159. * - `nonce`: client's nonce
  160. * - `signature`: client's signature over all previous params, plus the relay and RelayHub addresses
  161. * - `approvalData`: dapp-specific data forwarded to {acceptRelayedCall}. This value is *not* verified by the
  162. * `RelayHub`, but it still can be used for e.g. a signature.
  163. *
  164. * Emits a {TransactionRelayed} event.
  165. */
  166. function relayCall(
  167. address from,
  168. address to,
  169. bytes calldata encodedFunction,
  170. uint256 transactionFee,
  171. uint256 gasPrice,
  172. uint256 gasLimit,
  173. uint256 nonce,
  174. bytes calldata signature,
  175. bytes calldata approvalData
  176. ) external;
  177. /**
  178. * @dev Emitted when an attempt to relay a call failed.
  179. *
  180. * This can happen due to incorrect {relayCall} arguments, or the recipient not accepting the relayed call. The
  181. * actual relayed call was not executed, and the recipient not charged.
  182. *
  183. * The `reason` parameter contains an error code: values 1-10 correspond to `PreconditionCheck` entries, and values
  184. * over 10 are custom recipient error codes returned from {acceptRelayedCall}.
  185. */
  186. event CanRelayFailed(address indexed relay, address indexed from, address indexed to, bytes4 selector, uint256 reason);
  187. /**
  188. * @dev Emitted when a transaction is relayed.
  189. * Useful when monitoring a relay's operation and relayed calls to a contract
  190. *
  191. * Note that the actual encoded function might be reverted: this is indicated in the `status` parameter.
  192. *
  193. * `charge` is the Ether value deducted from the recipient's balance, paid to the relay's owner.
  194. */
  195. event TransactionRelayed(address indexed relay, address indexed from, address indexed to, bytes4 selector, RelayCallStatus status, uint256 charge);
  196. // Reason error codes for the TransactionRelayed event
  197. enum RelayCallStatus {
  198. OK, // The transaction was successfully relayed and execution successful - never included in the event
  199. RelayedCallFailed, // The transaction was relayed, but the relayed call failed
  200. PreRelayedFailed, // The transaction was not relayed due to preRelatedCall reverting
  201. PostRelayedFailed, // The transaction was relayed and reverted due to postRelatedCall reverting
  202. RecipientBalanceChanged // The transaction was relayed and reverted due to the recipient's balance changing
  203. }
  204. /**
  205. * @dev Returns how much gas should be forwarded to a call to {relayCall}, in order to relay a transaction that will
  206. * spend up to `relayedCallStipend` gas.
  207. */
  208. function requiredGas(uint256 relayedCallStipend) external view returns (uint256);
  209. /**
  210. * @dev Returns the maximum recipient charge, given the amount of gas forwarded, gas price and relay fee.
  211. */
  212. function maxPossibleCharge(uint256 relayedCallStipend, uint256 gasPrice, uint256 transactionFee) external view returns (uint256);
  213. // Relay penalization.
  214. // Any account can penalize relays, removing them from the system immediately, and rewarding the
  215. // reporter with half of the relay's stake. The other half is burned so that, even if the relay penalizes itself, it
  216. // still loses half of its stake.
  217. /**
  218. * @dev Penalize a relay that signed two transactions using the same nonce (making only the first one valid) and
  219. * different data (gas price, gas limit, etc. may be different).
  220. *
  221. * The (unsigned) transaction data and signature for both transactions must be provided.
  222. */
  223. function penalizeRepeatedNonce(bytes calldata unsignedTx1, bytes calldata signature1, bytes calldata unsignedTx2, bytes calldata signature2) external;
  224. /**
  225. * @dev Penalize a relay that sent a transaction that didn't target ``RelayHub``'s {registerRelay} or {relayCall}.
  226. */
  227. function penalizeIllegalTransaction(bytes calldata unsignedTx, bytes calldata signature) external;
  228. /**
  229. * @dev Emitted when a relay is penalized.
  230. */
  231. event Penalized(address indexed relay, address sender, uint256 amount);
  232. /**
  233. * @dev Returns an account's nonce in `RelayHub`.
  234. */
  235. function getNonce(address from) external view returns (uint256);
  236. }