V 1
Contracts
ECDSA
→ addressinternal
recover(bytes32 hash, bytes signature)Returns the address that signed a hashed message (hash
) with
signature
. This address can then be used for verification purposes.
The ecrecover
EVM opcode allows for malleable (non-unique) signatures:
this function rejects them by requiring the s
value to be in the lower
half order, and the v
value to be either 27 or 28.
(.note) This call does not revert if the signature is invalid, or if the signer is otherwise unable to be retrieved. In those scenarios, the zero address is returned.
(.warning) hash
must be the result of a hash operation for the
verification to be secure: it is possible to craft signatures that
recover to arbitrary addresses for non-hashed data. A safe way to ensure
this is by receiving a hash of the original message (which may otherwise)
be too long), and then calling toEthSignedMessageHash
on it.
→ bytes32internal
toEthSignedMessageHash(bytes32 hash)Returns an Ethereum Signed Message, created from a hash
. This
replicates the behavior of the
eth_sign
JSON-RPC method.
See recover
.
GsnUtils
→ bytes4internal
getMethodSig(bytes msgData)→ uint256internal
getParam(bytes msgData, uint256 index)→ bytesinternal
getBytesParam(bytes msgData, uint256 index)→ stringinternal
getStringParam(bytes msgData, uint256 index)→ boolinternal
checkSig(address signer, bytes32 hash, bytes sig)IRelayHub
stake(address relayaddr, uint256 unstakeDelay)
registerRelay(uint256 transactionFee, string url)
removeRelayByOwner(address relay)
unstake(address relay)
getRelay(address relay)
depositFor(address target)
balanceOf(address target)
withdraw(uint256 amount, address payable dest)
canRelay(address relay, address from, address to, bytes encodedFunction, uint256 transactionFee, uint256 gasPrice, uint256 gasLimit, uint256 nonce, bytes signature, bytes approvalData)
relayCall(address from, address to, bytes encodedFunction, uint256 transactionFee, uint256 gasPrice, uint256 gasLimit, uint256 nonce, bytes signature, bytes approvalData)
requiredGas(uint256 relayedCallStipend)
maxPossibleCharge(uint256 relayedCallStipend, uint256 gasPrice, uint256 transactionFee)
penalizeRepeatedNonce(bytes unsignedTx1, bytes signature1, bytes unsignedTx2, bytes signature2)
penalizeIllegalTransaction(bytes unsignedTx, bytes signature)
getNonce(address from)
Staked(address relay, uint256 stake, uint256 unstakeDelay)
RelayAdded(address relay, address owner, uint256 transactionFee, uint256 stake, uint256 unstakeDelay, string url)
RelayRemoved(address relay, uint256 unstakeTime)
Unstaked(address relay, uint256 stake)
Deposited(address recipient, address from, uint256 amount)
Withdrawn(address account, address dest, uint256 amount)
CanRelayFailed(address relay, address from, address to, bytes4 selector, uint256 reason)
TransactionRelayed(address relay, address from, address to, bytes4 selector, enum IRelayHub.RelayCallStatus status, uint256 charge)
Penalized(address relay, address sender, uint256 amount)
stake(address relayaddr, uint256 unstakeDelay)
external
Adds 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.
registerRelay(uint256 transactionFee, string url)
external
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).
This function can be called multiple times, emitting new {RelayAdded} events. Note that the received
transactionFee
is not enforced by {relayCall}.
Emits a {RelayAdded} event.
removeRelayByOwner(address relay)
external
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.
unstake(address relay)
external
→ uint256,uint256,uint256,address payable,enum IRelayHub.RelayStateexternal
getRelay(address relay)Returns a relay's status. Note that relays can be deleted when unstaked or penalized, causing this function to return an empty entry.
depositFor(address target)
external
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 calling {withdraw}.
Emits a {Deposited} event.
→ uint256external
balanceOf(address target)Returns an account's deposits. These can be either a contracts's funds, or a relay owner's revenue.
withdraw(uint256 amount, address payable dest)
external
→ uint256,bytesexternal
canRelay(address relay, address from, address to, bytes encodedFunction, uint256 transactionFee, uint256 gasPrice, uint256 gasLimit, uint256 nonce, bytes signature, bytes approvalData)Checks 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}.
relayCall(address from, address to, bytes encodedFunction, uint256 transactionFee, uint256 gasPrice, uint256 gasLimit, uint256 nonce, bytes signature, bytes approvalData)
external
Relays a transaction.
For this to succeed, 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 that order.
Parameters:
from
: the client originating the requestto
: the target {IRelayRecipient} contractencodedFunction
: the function call to relay, including datatransactionFee
: fee (%) the relay takes over actual gas costgasPrice
: gas price the client is willing to paygasLimit
: gas to forward when calling the encoded functionnonce
: client's noncesignature
: client's signature over all previous params, plus the relay and RelayHub addressesapprovalData
: dapp-specific data forwared to {acceptRelayedCall}. This value is not verified by theRelayHub
, but it still can be used for e.g. a signature.
Emits a {TransactionRelayed} event.
→ uint256external
requiredGas(uint256 relayedCallStipend)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.
→ uint256external
maxPossibleCharge(uint256 relayedCallStipend, uint256 gasPrice, uint256 transactionFee)Returns the maximum recipient charge, given the amount of gas forwarded, gas price and relay fee.
penalizeRepeatedNonce(bytes unsignedTx1, bytes signature1, bytes unsignedTx2, bytes signature2)
external
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.
penalizeIllegalTransaction(bytes unsignedTx, bytes signature)
external
Penalize a relay that sent a transaction that didn't target RelayHub
's {registerRelay} or {relayCall}.
→ uint256external
getNonce(address from)Returns an account's nonce in RelayHub
.
Staked(address relay, uint256 stake, uint256 unstakeDelay)
Emitted when a relay's stake or unstakeDelay are increased
RelayAdded(address relay, address owner, uint256 transactionFee, uint256 stake, uint256 unstakeDelay, string url)
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.
RelayRemoved(address relay, uint256 unstakeTime)
Emitted when a relay is removed (deregistered). unstakeTime
is the time when unstake will be callable.
Unstaked(address relay, uint256 stake)
Emitted when a relay is unstaked for, including the returned stake.
Deposited(address recipient, address from, uint256 amount)
Emitted when {depositFor} is called, including the amount and account that was funded.
Withdrawn(address account, address dest, uint256 amount)
Emitted when an account withdraws funds from RelayHub
.
CanRelayFailed(address relay, address from, address to, bytes4 selector, uint256 reason)
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
parameter contains an error code: values 1-10 correspond to PreconditionCheck
entries, and values
over 10 are custom recipient error codes returned from {acceptRelayedCall}.
TransactionRelayed(address relay, address from, address to, bytes4 selector, enum IRelayHub.RelayCallStatus status, uint256 charge)
Emitted when a transaction is relayed. Useful when monitoring a relay's operation and relayed calls to a contract
Note that the actual encoded function might be reverted: this is indicated in the status
parameter.
charge
is the Ether value deducted from the recipient's balance, paid to the relay's owner.
Penalized(address relay, address sender, uint256 amount)
Emitted when a relay is penalized.
IRelayRecipient
getHubAddr()
acceptRelayedCall(address relay, address from, bytes encodedFunction, uint256 transactionFee, uint256 gasPrice, uint256 gasLimit, uint256 nonce, bytes approvalData, uint256 maxPossibleCharge)
preRelayedCall(bytes context)
postRelayedCall(bytes context, bool success, uint256 actualCharge, bytes32 preRetVal)
→ addressexternal
getHubAddr()Returns the address of the {IRelayHub} instance this recipient interacts with.
→ uint256,bytesexternal
acceptRelayedCall(address relay, address from, bytes encodedFunction, uint256 transactionFee, uint256 gasPrice, uint256 gasLimit, uint256 nonce, bytes approvalData, uint256 maxPossibleCharge)Called by {IRelayHub} to validate if this recipient accepts being charged for a relayed call. Note that the recipient will be charged regardless of the execution result of the relayed call (i.e. if it reverts or not).
The relay request was originated by from
and will be served by relay
. encodedFunction
is the relayed call
calldata, so its first four bytes are the function selector. The relayed call will be forwarded gasLimit
gas,
and the transaction executed with a gas price of at least gasPrice
. relay
's fee is transactionFee
, and the
recipient will be charged at most maxPossibleCharge
(in wei). nonce
is the sender's (from
) nonce for
replay attack protection in {IRelayHub}, and approvalData
is a optional parameter that can be used to hold a signature
over all or some of the previous values.
Returns a tuple, where the first value is used to indicate approval (0) or rejection (custom non-zero error code, values 1 to 10 are reserved) and the second one is data to be passed to the other {IRelayRecipient} functions.
{acceptRelayedCall} is called with 50k gas: if it runs out during execution, the request will be considered rejected. A regular revert will also trigger a rejection.
→ bytes32external
preRelayedCall(bytes context)Called by {IRelayHub} on approved relay call requests, before the relayed call is executed. This allows to e.g. pre-charge the sender of the transaction.
context
is the second value returned in the tuple by {acceptRelayedCall}.
Returns a value to be passed to {postRelayedCall}.
{preRelayedCall} is called with 100k gas: if it runs out during exection or otherwise reverts, the relayed call will not be executed, but the recipient will still be charged for the transaction's cost.
postRelayedCall(bytes context, bool success, uint256 actualCharge, bytes32 preRetVal)
external
Called by {IRelayHub} on approved relay call requests, after the relayed call is executed. This allows to e.g. charge the user for the relayed call costs, return any overcharges from {preRelayedCall}, or perform contract-specific bookkeeping.
context
is the second value returned in the tuple by {acceptRelayedCall}. success
is the execution status of
the relayed call. actualCharge
is an estimate of how much the recipient will be charged for the transaction,
not including any gas used by {postRelayedCall} itself. preRetVal
is {preRelayedCall}'s return value.
{postRelayedCall} is called with 100k gas: if it runs out during execution or otherwise reverts, the relayed call and the call to {preRelayedCall} will be reverted retroactively, but the recipient will still be charged for the transaction's cost.
LibBytes
rawAddress(bytes input)
contentAddress(bytes input)
memCopy(uint256 dest, uint256 source, uint256 length)
slice(bytes b, uint256 from, uint256 to)
sliceDestructive(bytes b, uint256 from, uint256 to)
popLastByte(bytes b)
equals(bytes lhs, bytes rhs)
readAddress(bytes b, uint256 index)
writeAddress(bytes b, uint256 index, address input)
readBytes32(bytes b, uint256 index)
writeBytes32(bytes b, uint256 index, bytes32 input)
readUint256(bytes b, uint256 index)
writeUint256(bytes b, uint256 index, uint256 input)
readBytes4(bytes b, uint256 index)
writeLength(bytes b, uint256 length)
→ uint256internal
rawAddress(bytes input)Gets the memory address for a byte array. @param input Byte array to lookup. @return memoryAddress Memory address of byte array. This points to the header of the byte array which contains the length.
→ uint256internal
contentAddress(bytes input)Gets the memory address for the contents of a byte array. @param input Byte array to lookup. @return memoryAddress Memory address of the contents of the byte array.
memCopy(uint256 dest, uint256 source, uint256 length)
internal
Copies length
bytes from memory location source
to dest
.
@param dest memory address to copy bytes to.
@param source memory address to copy bytes from.
@param length number of bytes to copy.
→ bytesinternal
slice(bytes b, uint256 from, uint256 to)Returns a slices from a byte array. @param b The byte array to take a slice from. @param from The starting index for the slice (inclusive). @param to The final index for the slice (exclusive). @return result The slice containing bytes at indices [from, to)
→ bytesinternal
sliceDestructive(bytes b, uint256 from, uint256 to)Returns a slice from a byte array without preserving the input.
@param b The byte array to take a slice from. Will be destroyed in the process.
@param from The starting index for the slice (inclusive).
@param to The final index for the slice (exclusive).
@return result The slice containing bytes at indices [from, to)
@dev When from == 0
, the original array will match the slice. In other cases its state will be corrupted.
→ bytes1internal
popLastByte(bytes b)Pops the last byte off of a byte array by modifying its length. @param b Byte array that will be modified. @return The byte that was popped off.
→ boolinternal
equals(bytes lhs, bytes rhs)Tests equality of two byte arrays. @param lhs First byte array to compare. @param rhs Second byte array to compare. @return True if arrays are the same. False otherwise.
→ addressinternal
readAddress(bytes b, uint256 index)Reads an address from a position in a byte array. @param b Byte array containing an address. @param index Index in byte array of address. @return address from byte array.
writeAddress(bytes b, uint256 index, address input)
internal
Writes an address into a specific position in a byte array. @param b Byte array to insert address into. @param index Index in byte array of address. @param input Address to put into byte array.
→ bytes32internal
readBytes32(bytes b, uint256 index)Reads a bytes32 value from a position in a byte array. @param b Byte array containing a bytes32 value. @param index Index in byte array of bytes32 value. @return bytes32 value from byte array.
writeBytes32(bytes b, uint256 index, bytes32 input)
internal
Writes a bytes32 into a specific position in a byte array. @param b Byte array to insert <input> into. @param index Index in byte array of <input>. @param input bytes32 to put into byte array.
→ uint256internal
readUint256(bytes b, uint256 index)Reads a uint256 value from a position in a byte array. @param b Byte array containing a uint256 value. @param index Index in byte array of uint256 value. @return uint256 value from byte array.
writeUint256(bytes b, uint256 index, uint256 input)
internal
Writes a uint256 into a specific position in a byte array. @param b Byte array to insert <input> into. @param index Index in byte array of <input>. @param input uint256 to put into byte array.
→ bytes4internal
readBytes4(bytes b, uint256 index)Reads an unpadded bytes4 value from a position in a byte array. @param b Byte array containing a bytes4 value. @param index Index in byte array of bytes4 value. @return bytes4 value from byte array.
writeLength(bytes b, uint256 length)
internal
Writes a new length to a byte array. Decreasing length will lead to removing the corresponding lower order bytes from the byte array. Increasing length may lead to appending adjacent in-memory bytes to the end of the byte array. @param b Bytes array to write new length to. @param length New length of byte array.
RLPReader
decodeTransaction(bytes rawTransaction)
toRlpItem(bytes item)
toList(struct RLPReader.RLPItem item)
isList(struct RLPReader.RLPItem item)
numItems(struct RLPReader.RLPItem item)
_itemLength(uint256 memPtr)
_payloadOffset(uint256 memPtr)
toRlpBytes(struct RLPReader.RLPItem item)
toBoolean(struct RLPReader.RLPItem item)
toAddress(struct RLPReader.RLPItem item)
toUint(struct RLPReader.RLPItem item)
toBytes(struct RLPReader.RLPItem item)
copy(uint256 src, uint256 dest, uint256 len)
→ uint256,uint256,uint256,address,uint256,bytesinternal
decodeTransaction(bytes rawTransaction)→ struct RLPReader.RLPIteminternal
toRlpItem(bytes item)→ struct RLPReader.RLPItem[]internal
toList(struct RLPReader.RLPItem item)→ boolinternal
isList(struct RLPReader.RLPItem item)→ uint256internal
numItems(struct RLPReader.RLPItem item)→ uint256internal
_itemLength(uint256 memPtr)→ uint256internal
_payloadOffset(uint256 memPtr)→ bytesinternal
toRlpBytes(struct RLPReader.RLPItem item)→ boolinternal
toBoolean(struct RLPReader.RLPItem item)→ addressinternal
toAddress(struct RLPReader.RLPItem item)→ uint256internal
toUint(struct RLPReader.RLPItem item)→ bytesinternal
toBytes(struct RLPReader.RLPItem item)copy(uint256 src, uint256 dest, uint256 len)
internal
RelayHub
stake(address relay, uint256 unstakeDelay)
registerRelay(uint256 transactionFee, string url)
removeRelayByOwner(address relay)
unstake(address relay)
getRelay(address relay)
depositFor(address target)
balanceOf(address target)
withdraw(uint256 amount, address payable dest)
getNonce(address from)
canUnstake(address relay)
canRelay(address relay, address from, address to, bytes encodedFunction, uint256 transactionFee, uint256 gasPrice, uint256 gasLimit, uint256 nonce, bytes signature, bytes approvalData)
relayCall(address from, address recipient, bytes encodedFunction, uint256 transactionFee, uint256 gasPrice, uint256 gasLimit, uint256 nonce, bytes signature, bytes approvalData)
recipientCallsAtomic(address recipient, bytes encodedFunctionWithFrom, uint256 transactionFee, uint256 gasPrice, uint256 gasLimit, uint256 preChecksGas, bytes recipientContext)
requiredGas(uint256 relayedCallStipend)
maxPossibleCharge(uint256 relayedCallStipend, uint256 gasPrice, uint256 transactionFee)
penalizeRepeatedNonce(bytes unsignedTx1, bytes signature1, bytes unsignedTx2, bytes signature2)
penalizeIllegalTransaction(bytes unsignedTx, bytes signature)
Staked(address relay, uint256 stake, uint256 unstakeDelay)
RelayAdded(address relay, address owner, uint256 transactionFee, uint256 stake, uint256 unstakeDelay, string url)
RelayRemoved(address relay, uint256 unstakeTime)
Unstaked(address relay, uint256 stake)
Deposited(address recipient, address from, uint256 amount)
Withdrawn(address account, address dest, uint256 amount)
CanRelayFailed(address relay, address from, address to, bytes4 selector, uint256 reason)
TransactionRelayed(address relay, address from, address to, bytes4 selector, enum IRelayHub.RelayCallStatus status, uint256 charge)
Penalized(address relay, address sender, uint256 amount)
stake(address relay, uint256 unstakeDelay)
external
registerRelay(uint256 transactionFee, string url)
public
removeRelayByOwner(address relay)
public
unstake(address relay)
public
→ uint256,uint256,uint256,address payable,enum IRelayHub.RelayStateexternal
getRelay(address relay)depositFor(address target)
public
→ uint256external
balanceOf(address target)withdraw(uint256 amount, address payable dest)
public
→ uint256external
getNonce(address from)→ boolpublic
canUnstake(address relay)→ uint256,bytespublic
canRelay(address relay, address from, address to, bytes encodedFunction, uint256 transactionFee, uint256 gasPrice, uint256 gasLimit, uint256 nonce, bytes signature, bytes approvalData)relayCall(address from, address recipient, bytes encodedFunction, uint256 transactionFee, uint256 gasPrice, uint256 gasLimit, uint256 nonce, bytes signature, bytes approvalData)
public
→ enum IRelayHub.RelayCallStatusexternal
recipientCallsAtomic(address recipient, bytes encodedFunctionWithFrom, uint256 transactionFee, uint256 gasPrice, uint256 gasLimit, uint256 preChecksGas, bytes recipientContext)→ uint256public
requiredGas(uint256 relayedCallStipend)→ uint256public
maxPossibleCharge(uint256 relayedCallStipend, uint256 gasPrice, uint256 transactionFee)penalizeRepeatedNonce(bytes unsignedTx1, bytes signature1, bytes unsignedTx2, bytes signature2)
public
penalizeIllegalTransaction(bytes unsignedTx, bytes signature)
public
SafeMath
→ uint256internal
add(uint256 a, uint256 b)Returns the addition of two unsigned integers, reverting on overflow.
Counterpart to Solidity's +
operator.
Requirements:
- Addition cannot overflow.
→ uint256internal
sub(uint256 a, uint256 b)Returns the subtraction of two unsigned integers, reverting on overflow (when the result is negative).
Counterpart to Solidity's -
operator.
Requirements:
- Subtraction cannot overflow.
→ uint256internal
mul(uint256 a, uint256 b)Returns the multiplication of two unsigned integers, reverting on overflow.
Counterpart to Solidity's *
operator.
Requirements:
- Multiplication cannot overflow.
→ uint256internal
div(uint256 a, uint256 b)Returns the integer division of two unsigned integers. Reverts on division by zero. The result is rounded towards zero.
Counterpart to Solidity's /
operator. Note: this function uses a
revert
opcode (which leaves remaining gas untouched) while Solidity
uses an invalid opcode to revert (consuming all remaining gas).
Requirements:
- The divisor cannot be zero.
→ uint256internal
mod(uint256 a, uint256 b)Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), Reverts when dividing by zero.
Counterpart to Solidity's %
operator. This function uses a revert
opcode (which leaves remaining gas untouched) while Solidity uses an
invalid opcode to revert (consuming all remaining gas).
Requirements:
- The divisor cannot be zero.