You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
189 lines
10 KiB
189 lines
10 KiB
6 years ago
|
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);
|
||
|
}
|
||
|
|