IRelayHub.sol 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. pragma solidity ^0.5.0;
  2. contract IRelayHub {
  3. // Relay management
  4. // Add stake to a relay and sets its unstakeDelay.
  5. // If the relay does not exist, it is created, and the caller
  6. // of this function becomes its owner. If the relay already exists, only the owner can call this function. A relay
  7. // cannot be its own owner.
  8. // All Ether in this function call will be added to the relay's stake.
  9. // Its unstake delay will be assigned to unstakeDelay, but the new value must be greater or equal to the current one.
  10. // Emits a Staked event.
  11. function stake(address relayaddr, uint256 unstakeDelay) external payable;
  12. // Emited when a relay's stake or unstakeDelay are increased
  13. event Staked(address indexed relay, uint256 stake, uint256 unstakeDelay);
  14. // Registers the caller as a relay.
  15. // The relay must be staked for, and not be a contract (i.e. this function must be called directly from an EOA).
  16. // Emits a RelayAdded event.
  17. // This function can be called multiple times, emitting new RelayAdded events. Note that the received transactionFee
  18. // is not enforced by relayCall.
  19. function registerRelay(uint256 transactionFee, string memory url) public;
  20. // Emitted when a relay is registered or re-registerd. Looking at these events (and filtering out RelayRemoved
  21. // events) lets a client discover the list of available relays.
  22. event RelayAdded(address indexed relay, address indexed owner, uint256 transactionFee, uint256 stake, uint256 unstakeDelay, string url);
  23. // Removes (deregisters) a relay. Unregistered (but staked for) relays can also be removed. Can only be called by
  24. // the owner of the relay. After the relay's unstakeDelay has elapsed, unstake will be callable.
  25. // Emits a RelayRemoved event.
  26. function removeRelayByOwner(address relay) public;
  27. // Emitted when a relay is removed (deregistered). unstakeTime is the time when unstake will be callable.
  28. event RelayRemoved(address indexed relay, uint256 unstakeTime);
  29. // Deletes the relay from the system, and gives back its stake to the owner. Can only be called by the relay owner,
  30. // after unstakeDelay has elapsed since removeRelayByOwner was called.
  31. // Emits an Unstaked event.
  32. function unstake(address relay) public;
  33. // Emitted when a relay is unstaked for, including the returned stake.
  34. event Unstaked(address indexed relay, uint256 stake);
  35. // States a relay can be in
  36. enum RelayState {
  37. Unknown, // The relay is unknown to the system: it has never been staked for
  38. Staked, // The relay has been staked for, but it is not yet active
  39. Registered, // The relay has registered itself, and is active (can relay calls)
  40. 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
  41. }
  42. // Returns a relay's status. Note that relays can be deleted when unstaked or penalized.
  43. function getRelay(address relay) external view returns (uint256 totalStake, uint256 unstakeDelay, uint256 unstakeTime, address payable owner, RelayState state);
  44. // Balance management
  45. // Deposits ether for a contract, so that it can receive (and pay for) relayed transactions. Unused balance can only
  46. // be withdrawn by the contract itself, by callingn withdraw.
  47. // Emits a Deposited event.
  48. function depositFor(address target) public payable;
  49. // Emitted when depositFor is called, including the amount and account that was funded.
  50. event Deposited(address indexed recipient, address indexed from, uint256 amount);
  51. // Returns an account's deposits. These can be either a contnract's funds, or a relay owner's revenue.
  52. function balanceOf(address target) external view returns (uint256);
  53. // Withdraws from an account's balance, sending it back to it. Relay owners call this to retrieve their revenue, and
  54. // contracts can also use it to reduce their funding.
  55. // Emits a Withdrawn event.
  56. function withdraw(uint256 amount, address payable dest) public;
  57. // Emitted when an account withdraws funds from RelayHub.
  58. event Withdrawn(address indexed account, address indexed dest, uint256 amount);
  59. // Relaying
  60. // Check if the RelayHub will accept a relayed operation. Multiple things must be true for this to happen:
  61. // - all arguments must be signed for by the sender (from)
  62. // - the sender's nonce must be the current one
  63. // - the recipient must accept this transaction (via acceptRelayedCall)
  64. // Returns a PreconditionCheck value (OK when the transaction can be relayed), or a recipient-specific error code if
  65. // it returns one in acceptRelayedCall.
  66. function canRelay(
  67. address relay,
  68. address from,
  69. address to,
  70. bytes memory encodedFunction,
  71. uint256 transactionFee,
  72. uint256 gasPrice,
  73. uint256 gasLimit,
  74. uint256 nonce,
  75. bytes memory signature,
  76. bytes memory approvalData
  77. ) public view returns (uint256 status, bytes memory recipientContext);
  78. // Preconditions for relaying, checked by canRelay and returned as the corresponding numeric values.
  79. enum PreconditionCheck {
  80. OK, // All checks passed, the call can be relayed
  81. WrongSignature, // The transaction to relay is not signed by requested sender
  82. WrongNonce, // The provided nonce has already been used by the sender
  83. AcceptRelayedCallReverted, // The recipient rejected this call via acceptRelayedCall
  84. InvalidRecipientStatusCode // The recipient returned an invalid (reserved) status code
  85. }
  86. // Relays a transaction. For this to suceed, multiple conditions must be met:
  87. // - canRelay must return PreconditionCheck.OK
  88. // - the sender must be a registered relay
  89. // - the transaction's gas price must be larger or equal to the one that was requested by the sender
  90. // - the transaction must have enough gas to not run out of gas if all internal transactions (calls to the
  91. // recipient) use all gas available to them
  92. // - the recipient must have enough balance to pay the relay for the worst-case scenario (i.e. when all gas is
  93. // spent)
  94. //
  95. // If all conditions are met, the call will be relayed and the recipient charged. preRelayedCall, the encoded
  96. // function and postRelayedCall will be called in order.
  97. //
  98. // Arguments:
  99. // - from: the client originating the request
  100. // - recipient: the target IRelayRecipient contract
  101. // - encodedFunction: the function call to relay, including data
  102. // - transactionFee: fee (%) the relay takes over actual gas cost
  103. // - gasPrice: gas price the client is willing to pay
  104. // - gasLimit: gas to forward when calling the encoded function
  105. // - nonce: client's nonce
  106. // - signature: client's signature over all previous params, plus the relay and RelayHub addresses
  107. // - approvalData: dapp-specific data forwared to acceptRelayedCall. This value is *not* verified by the Hub, but
  108. // it still can be used for e.g. a signature.
  109. //
  110. // Emits a TransactionRelayed event.
  111. function relayCall(
  112. address from,
  113. address to,
  114. bytes memory encodedFunction,
  115. uint256 transactionFee,
  116. uint256 gasPrice,
  117. uint256 gasLimit,
  118. uint256 nonce,
  119. bytes memory signature,
  120. bytes memory approvalData
  121. ) public;
  122. // Emitted when an attempt to relay a call failed. This can happen due to incorrect relayCall arguments, or the
  123. // recipient not accepting the relayed call. The actual relayed call was not executed, and the recipient not charged.
  124. // The reason field contains an error code: values 1-10 correspond to PreconditionCheck entries, and values over 10
  125. // are custom recipient error codes returned from acceptRelayedCall.
  126. event CanRelayFailed(address indexed relay, address indexed from, address indexed to, bytes4 selector, uint256 reason);
  127. // Emitted when a transaction is relayed. Note that the actual encoded function might be reverted: this will be
  128. // indicated in the status field.
  129. // Useful when monitoring a relay's operation and relayed calls to a contract.
  130. // Charge is the ether value deducted from the recipient's balance, paid to the relay's owner.
  131. event TransactionRelayed(address indexed relay, address indexed from, address indexed to, bytes4 selector, RelayCallStatus status, uint256 charge);
  132. // Reason error codes for the TransactionRelayed event
  133. enum RelayCallStatus {
  134. OK, // The transaction was successfully relayed and execution successful - never included in the event
  135. RelayedCallFailed, // The transaction was relayed, but the relayed call failed
  136. PreRelayedFailed, // The transaction was not relayed due to preRelatedCall reverting
  137. PostRelayedFailed, // The transaction was relayed and reverted due to postRelatedCall reverting
  138. RecipientBalanceChanged // The transaction was relayed and reverted due to the recipient's balance changing
  139. }
  140. // Returns how much gas should be forwarded to a call to relayCall, in order to relay a transaction that will spend
  141. // up to relayedCallStipend gas.
  142. function requiredGas(uint256 relayedCallStipend) public view returns (uint256);
  143. // Returns the maximum recipient charge, given the amount of gas forwarded, gas price and relay fee.
  144. function maxPossibleCharge(uint256 relayedCallStipend, uint256 gasPrice, uint256 transactionFee) public view returns (uint256);
  145. // Relay penalization. Any account can penalize relays, removing them from the system immediately, and rewarding the
  146. // reporter with half of the relay's stake. The other half is burned so that, even if the relay penalizes itself, it
  147. // still loses half of its stake.
  148. // Penalize a relay that signed two transactions using the same nonce (making only the first one valid) and
  149. // different data (gas price, gas limit, etc. may be different). The (unsigned) transaction data and signature for
  150. // both transactions must be provided.
  151. function penalizeRepeatedNonce(bytes memory unsignedTx1, bytes memory signature1, bytes memory unsignedTx2, bytes memory signature2) public;
  152. // Penalize a relay that sent a transaction that didn't target RelayHub's registerRelay or relayCall.
  153. function penalizeIllegalTransaction(bytes memory unsignedTx, bytes memory signature) public;
  154. event Penalized(address indexed relay, address sender, uint256 amount);
  155. function getNonce(address from) external view returns (uint256);
  156. }