123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- pragma solidity ^0.5.0;
- contract IRelayHub {
- // Relay management
- // Add stake to a relay and sets its unstakeDelay.
- // If the relay does not exist, it is created, and the caller
- // of this function becomes its owner. If the relay already exists, only the owner can call this function. A relay
- // cannot be its own owner.
- // All Ether in this function call will be added to the relay's stake.
- // Its unstake delay will be assigned to unstakeDelay, but the new value must be greater or equal to the current one.
- // Emits a Staked event.
- function stake(address relayaddr, uint256 unstakeDelay) external payable;
- // Emited when a relay's stake or unstakeDelay are increased
- event Staked(address indexed relay, uint256 stake, uint256 unstakeDelay);
- // Registers the caller as a relay.
- // The relay must be staked for, and not be a contract (i.e. this function must be called directly from an EOA).
- // Emits a RelayAdded event.
- // This function can be called multiple times, emitting new RelayAdded events. Note that the received transactionFee
- // is not enforced by relayCall.
- function registerRelay(uint256 transactionFee, string memory url) public;
- // Emitted when a relay is registered or re-registerd. Looking at these events (and filtering out RelayRemoved
- // events) lets a client discover the list of available relays.
- event RelayAdded(address indexed relay, address indexed owner, uint256 transactionFee, uint256 stake, uint256 unstakeDelay, string url);
- // Removes (deregisters) a relay. Unregistered (but staked for) relays can also be removed. Can only be called by
- // the owner of the relay. After the relay's unstakeDelay has elapsed, unstake will be callable.
- // Emits a RelayRemoved event.
- function removeRelayByOwner(address relay) public;
- // Emitted when a relay is removed (deregistered). unstakeTime is the time when unstake will be callable.
- event RelayRemoved(address indexed relay, uint256 unstakeTime);
- // Deletes the relay from the system, and gives back its stake to the owner. Can only be called by the relay owner,
- // after unstakeDelay has elapsed since removeRelayByOwner was called.
- // Emits an Unstaked event.
- function unstake(address relay) public;
- // Emitted when a relay is unstaked for, including the returned stake.
- event Unstaked(address indexed relay, uint256 stake);
- // States a relay can be in
- enum RelayState {
- Unknown, // The relay is unknown to the system: it has never been staked for
- Staked, // The relay has been staked for, but it is not yet active
- Registered, // The relay has registered itself, and is active (can relay calls)
- 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
- }
- // Returns a relay's status. Note that relays can be deleted when unstaked or penalized.
- function getRelay(address relay) external view returns (uint256 totalStake, uint256 unstakeDelay, uint256 unstakeTime, address payable owner, RelayState state);
- // Balance management
- // Deposits ether for a contract, so that it can receive (and pay for) relayed transactions. Unused balance can only
- // be withdrawn by the contract itself, by callingn withdraw.
- // Emits a Deposited event.
- function depositFor(address target) public payable;
- // Emitted when depositFor is called, including the amount and account that was funded.
- event Deposited(address indexed recipient, address indexed from, uint256 amount);
- // Returns an account's deposits. These can be either a contnract's funds, or a relay owner's revenue.
- function balanceOf(address target) external view returns (uint256);
- // Withdraws from an account's balance, sending it back to it. Relay owners call this to retrieve their revenue, and
- // contracts can also use it to reduce their funding.
- // Emits a Withdrawn event.
- function withdraw(uint256 amount, address payable dest) public;
- // Emitted when an account withdraws funds from RelayHub.
- event Withdrawn(address indexed account, address indexed dest, uint256 amount);
- // Relaying
- // Check if the RelayHub will accept a relayed operation. Multiple things must be true for this to happen:
- // - all arguments must be signed for by the sender (from)
- // - the sender's nonce must be the current one
- // - the recipient must accept this transaction (via acceptRelayedCall)
- // Returns a PreconditionCheck value (OK when the transaction can be relayed), or a recipient-specific error code if
- // it returns one in acceptRelayedCall.
- function canRelay(
- address relay,
- address from,
- address to,
- bytes memory encodedFunction,
- uint256 transactionFee,
- uint256 gasPrice,
- uint256 gasLimit,
- uint256 nonce,
- bytes memory signature,
- bytes memory approvalData
- ) public view returns (uint256 status, bytes memory recipientContext);
- // Preconditions for relaying, checked by canRelay and returned as the corresponding numeric values.
- enum PreconditionCheck {
- OK, // All checks passed, the call can be relayed
- WrongSignature, // The transaction to relay is not signed by requested sender
- WrongNonce, // The provided nonce has already been used by the sender
- AcceptRelayedCallReverted, // The recipient rejected this call via acceptRelayedCall
- InvalidRecipientStatusCode // The recipient returned an invalid (reserved) status code
- }
- // Relays a transaction. For this to suceed, multiple conditions must be met:
- // - canRelay must return PreconditionCheck.OK
- // - the sender must be a registered relay
- // - the transaction's gas price must be larger or equal to the one that was requested by the sender
- // - the transaction must have enough gas to not run out of gas if all internal transactions (calls to the
- // recipient) use all gas available to them
- // - the recipient must have enough balance to pay the relay for the worst-case scenario (i.e. when all gas is
- // spent)
- //
- // If all conditions are met, the call will be relayed and the recipient charged. preRelayedCall, the encoded
- // function and postRelayedCall will be called in order.
- //
- // Arguments:
- // - from: the client originating the request
- // - recipient: the target IRelayRecipient contract
- // - encodedFunction: the function call to relay, including data
- // - transactionFee: fee (%) the relay takes over actual gas cost
- // - gasPrice: gas price the client is willing to pay
- // - gasLimit: gas to forward when calling the encoded function
- // - nonce: client's nonce
- // - signature: client's signature over all previous params, plus the relay and RelayHub addresses
- // - approvalData: dapp-specific data forwared to acceptRelayedCall. This value is *not* verified by the Hub, but
- // it still can be used for e.g. a signature.
- //
- // Emits a TransactionRelayed event.
- function relayCall(
- address from,
- address to,
- bytes memory encodedFunction,
- uint256 transactionFee,
- uint256 gasPrice,
- uint256 gasLimit,
- uint256 nonce,
- bytes memory signature,
- bytes memory approvalData
- ) public;
- // Emitted when an attempt to relay a call failed. This can happen due to incorrect relayCall arguments, or the
- // recipient not accepting the relayed call. The actual relayed call was not executed, and the recipient not charged.
- // The reason field contains an error code: values 1-10 correspond to PreconditionCheck entries, and values over 10
- // are custom recipient error codes returned from acceptRelayedCall.
- event CanRelayFailed(address indexed relay, address indexed from, address indexed to, bytes4 selector, uint256 reason);
- // Emitted when a transaction is relayed. Note that the actual encoded function might be reverted: this will be
- // indicated in the status field.
- // Useful when monitoring a relay's operation and relayed calls to a contract.
- // Charge is the ether value deducted from the recipient's balance, paid to the relay's owner.
- event TransactionRelayed(address indexed relay, address indexed from, address indexed to, bytes4 selector, RelayCallStatus status, uint256 charge);
- // Reason error codes for the TransactionRelayed event
- enum RelayCallStatus {
- OK, // The transaction was successfully relayed and execution successful - never included in the event
- RelayedCallFailed, // The transaction was relayed, but the relayed call failed
- PreRelayedFailed, // The transaction was not relayed due to preRelatedCall reverting
- PostRelayedFailed, // The transaction was relayed and reverted due to postRelatedCall reverting
- RecipientBalanceChanged // The transaction was relayed and reverted due to the recipient's balance changing
- }
- // Returns how much gas should be forwarded to a call to relayCall, in order to relay a transaction that will spend
- // up to relayedCallStipend gas.
- function requiredGas(uint256 relayedCallStipend) public view returns (uint256);
- // Returns the maximum recipient charge, given the amount of gas forwarded, gas price and relay fee.
- function maxPossibleCharge(uint256 relayedCallStipend, uint256 gasPrice, uint256 transactionFee) public view returns (uint256);
- // Relay penalization. Any account can penalize relays, removing them from the system immediately, and rewarding the
- // reporter with half of the relay's stake. The other half is burned so that, even if the relay penalizes itself, it
- // still loses half of its stake.
- // Penalize a relay that signed two transactions using the same nonce (making only the first one valid) and
- // different data (gas price, gas limit, etc. may be different). The (unsigned) transaction data and signature for
- // both transactions must be provided.
- function penalizeRepeatedNonce(bytes memory unsignedTx1, bytes memory signature1, bytes memory unsignedTx2, bytes memory signature2) public;
- // Penalize a relay that sent a transaction that didn't target RelayHub's registerRelay or relayCall.
- function penalizeIllegalTransaction(bytes memory unsignedTx, bytes memory signature) public;
- event Penalized(address indexed relay, address sender, uint256 amount);
- function getNonce(address from) external view returns (uint256);
- }
|