---
# System prepended metadata

title: Silent Relayers
tags: [Silent Protocol's Components, Silent's Relayer]

---

<!-- ###### tags: `SILENT` -->

# Silent Relayers

This document provides an overview of Silent's Relayer network.

## The Problem

Due to the open and transparent nature of the Ethereum blockchain. Every transaction which occurs on chain can be viewed by anybody. Despite this being useful, there are times when on chain privacy is required.

Silent Protocol solves the privacy issue by enabling anonymous DeFi interaction and private on chain transactions through Zero-Knowlege Proofs, Encryption, a Multi-Asset Shielded Pool (MASP) and Stealth Addresses. 

Without an intermediary system to act on behalf of Silent users, the link between the user's account and their corresponding Silent account can be observable.

To tackle this problem, Silent Protocol leverages OpenGSN's [Ethereum Gas Station Network (GSN)](https://docs.opengsn.org/) implementation by utilizing a decentralised network of Relayers (Relay Servers / Services) that act as this intermediary to ensure privacy of protocol accounts.

## Architecture
![](https://hackmd.io/_uploads/H11IxowI2.png)

### Components
- Client (Front End): Selects Relayer. Signs and sends meta transactions to the paymaster service.
- Paymaster Service: Verifies, encodes and forwards messages to the chosen Relay service. Agrees to refund chosen Relayer for gas fees.
    - Signer Network: Signs encoded messages on behalf of the paymaster.
- Relay Service: Submits the transaction on behalf of the sender and pays the required gas fees in the process.
- Forwarder: Verifies the paymaster's signature and nonce and executes relay requests on the target contract.
- Relay Hub: Coordinates relay requests in a trustless manner. 

**Client (Front End): Selects Relayer. Signs and sends meta transactions to the paymaster service**

A meta transaction is a transaction that decouples the sender of a transaction and the payer of gas.

At this stage:
- A user selects their preferred Relayer from a list of available Relay servers. 
- Instead of signing an Ethereum transaction which requires gas, the user signs an encrypted message containing information about a transaction they would like to execute using their web3 wallet.
- Sends signed encrypted message to Silent’s Paymaster Service via an HTTP request.

**Paymaster Service: Verifies, encodes and forwards messages to the chosen Relay service. Agrees to refund chosen Relayer for gas fees**

Upon receiving the meta transaction request from the client, the Paymaster Service will validate this transaction by:
- Decrypting the signed message
- Verifying user’s signature
- Ensuring the user has enough Silent tokens to pay back the amount of ETH that covers the expenses of submitting the transaction plus an extra fee (incentive) for the Relayer they chose.

In the Silent Protocol, all gas refund logic is implemented inside the Paymaster contract. The paymaster maintains a Silent token balance in the RelayHub and uses this balance to refund Relayers for executing transactions on behalf of Silent users. In other words, relayers pay for gas using ETH and are refunded the equivalent plus an incentive using Silent tokens.

Thus, if the user passes validation, the paymaster service would agree to refund the Relayer by resigning the message using the Signer network and forwards it to the chosen Relayer for execution via an HTTP request.

**Relay Service: Submits the transaction on behalf of the sender and pays the required gas fees in the process**

Upon receiving the request from the Paymaster Service, the Relayer:
- Signs a native Ethereum transaction
- Submits the transaction to the mempool paying the gas cost
- Returns a signed transaction to the client for validation 

If anything goes wrong, the client can resend their meta-transaction using a different Relayer.

All Relayers (workers) on the network and the actual relaying of transactions are handled through Silent’s RelayHub smart contract.

**Forwarder: Verifies the paymaster’s signature and nonce and executes relay requests on the target contract**

Meta transaction-aware target contracts only rely on a small trusted forwarder contract for their security. This contract preserves the identity of the user that originally requested the transaction by verifying the signature and nonce of the paymaster who has already verified the signature of the original sender.

If all checks out, the forwarder executes the relay request on the target contract.

**Relay Hub: Coordinates requests in a trustless manner**

Silent’s RelayHub smart contract connects Silent Dapp users, Silent Relayers, and the Paymaster contract together so that participants do not need to know about or trust each other.

Dapp developers do not need to understand or trust the inner workings of RelayHub to integrate with Silent Relayers. Also, target contracts are not exposed to potential security issues in RelayHub.

Under the hood, the RelayHub contract help our users discover the best third-party relay servers, prevents third-party Relayers from censoring transactions, and ensures the Paymaster contract pays back Relayers for gas fees used plus any extra agreed fees.

## Protocol Primitives

### Notation
- $R, R_{id}$ : Relayer Server / Service
- $PS$ : Paymaster Service
- $PEOA$ : Paymaster Externally Owned Account with $(sk_P, pk_P, ea_P)$, Ethereum account secret key, public key and address, respectively. Can be used interchangeably with the threshold signature scheme (TSS) from the Signer network.
- $RHSC$ : RelayHub Smart Contract
- $PSC$ : Paymaster Smart Contract
- $RSC$ : Recipient / Target Smart Contract
- $TSC$ : ERC20 token contract (SilentToken) that will be used for fee payment
- $FSC$ : Forwarder Smart Contract
- $SRC$ : UniSwap Router Contract
- $c = E(pk, m)$: Public key encryption of message $m$ under the recipient's public key
- $m = D(sk, c)$: Public key decryption of ciphertext $c$ under the recipient's secret key
- $\sigma = S(sk, m)$: Digital signature on message $m$ under the signer's secret key
- $\{True,False\} = V(pk, m,\sigma)$: Signature verification of $\sigma$ on message $m$ under the signer's public key

### Paymaster Service

The first point of contact when a user makes a relay request through Silent’s UI.

- Responsible for managing and tracking user relayer deposits, withdrawals, charges, and balances.
- Verifies user's signatures and balances with respect to each relay request.
- Encodes and signs valid relay requests from users via the $POEA$ or by communicating directly with the Signer network.

For each User $U$, $PS$ records and tracks $U’s$ stealth public key $spk_U$, remaining balance $B_U$, previous signatures $\sigma_{U,i}$, and transaction history using a private and secure datastore.

#### Deposit

![](https://hackmd.io/_uploads/HkRjZvD8h.png)

1. Utilizing their Metamask wallet managed ETH address $(sk_U, pk_U, ea_U)$:
    - generates a RelayHub specific stealth address $(ssk_U,spk_U)$
    - deposits $a$ amount of ETH / SilentToken to $PSC$ with an input data that identifies the user’s stealth address in encrypted form, i.e. 
    $$c_U=E(pk_P,spk_U)$$

1. Upon a successful deposit, $PSC$ emits a deposit event which $PS$ tracks:
    - if this is initial deposit, adds the following to the datastore
        $$\{spk_U, B_U=a\}$$
    - if $spk_U$ already exists, updates corresponding entry as
        $$\{spk_U, B_U=B_U+a, \{\sigma_{U,i}\}\}$$

#### Relayer Service

![](https://hackmd.io/_uploads/BJcMAwD83.png)


1. User $U$ selects a relayer $R_{id}$ within the Silent UI relayer list
1. $U$ initiates a message payload $m$ with signed information addressed to $PS$
    $$(m,c’_U=E(pk_P,spk_U),\sigma_{U,i}=S(ssk_U,\{m,c’_U,R_{id}\}))$$
where:
    - $m$ is the actual transaction payload
    - $c’_U=E(pk_P,spk_U)$ is the encryption of $U's$ stealth public key $spk_U$ under $PEOA's$ public key $pk_P$
    - $\sigma_{U,i}==S(ssk_U,\{m,c’_U,R_{id}\})$ is the signature of $U$ on message $\{m,c’_U,R_{id}\}$ with their stealth private key $ssk_U$
1. Client forwards $U$ signed message to $PS$ via HTTPs
1. $PS$ verifies user signature with message and checks if user has enough funds for fee payment:
    - Decrypts $c’_U$ to get $spk_U=D(sk_P, c’_U)$
    - Verifies the user's signature, i.e $\{True\} = V(spk_U, \{m,c’_U,R_{id}\},\sigma_{U,i})$
    - Checks if $spk_U$ has enough funds $B_U$ for max fee payment 
    - Only then would it approve tx payload with its signature (through the Signer network), and sends it to the selected relayer, $R_{id}$
    $$(m,h(m,c’_U,\sigma_{U,i}), \sigma_P=S(sk_P,\{m, h(m,c’_U,\sigma_{U,i})\}))$$
    - Waits for successful tx, deduces the actual fee and updates $B_U$ in the database.

1. $R_{id}$ submits tx with $PEOA$ approval to RelayHub contract, $RHSC$
    $$(m,h(m,c’_U,\sigma_{U,i}), \sigma_P, txsig_{R_{id}})$$

1. $RSHC$ in conjuction with $PSC$ pursue the actual transaction phases and wait for succesful tx completion
1. Upon receiving a succesful tx, $RHSC$ coordinates with $PSC$ to pay relaying fees and updates balances to the relayer's $R_{id}$ account.
2. Events of successful allocation is captured by $R$ and sends request to $PS$ to also make appropriate balance adjustments

## Smart Contracts
This section describes the core functions of the various smart contracts involved in the Silent Relayer network. 

### RelayHub

#### Functions:
- **`relayCall`**
    Main function for sending a relay transaction.
    
    For this to succeed, multiple conditions must be met:
    - `Paymaster`'s `preRelayCall` method must pass and not revert.
    - `msg.sender` must be a registered Relayer that the user signed to use.
    - the transaction's gas fees must be equal or smaller than the ones that were signed by the sender.
    - the transaction must have enough gas to run all internal transactions if they use all gas available to them.
    - the `Paymaster` must have enough balance to pay the Relayer if all gas is spent.

    If all conditions are met, the call will be relayed and the `Paymaster` charged.
    
    Emits a `TransactionRelayed` event regardless of whether the transaction succeeded or failed.

    - params:
        - `maxAcceptanceBudget`: the maximum acceptable budget for gas limits
        - `relayRequest`: all details of the requested relayed call.
        - `signature`: the $POEA$ EIP-712 signature over the `relayRequest` struct. Used for verification in `Forwarder` contract 
        - `approvalData`: extra dapp-specific data
    - returns:
        - `paymasterAccepted`: boolean indicating whether `Paymaster` has accepted to refund the transaction
        - `charge`: amount of Silent tokens deducted from `Paymaster`'s managed balance
        - `status`: contains reasons for a revert if the actual internal function call reverts after transaction was relayed
        - `returnValue`: byte array containing return values, if any, from the internal function call

#### Types (Structs):
- **`RelayRequest`**:
    - `ForwarderRequest`: a representation of a request for a `Forwarder` to send `data` on behalf of a `from` to a target (`to`).
    - `RelayData`:  details of a transaction signed by the sender.
- **`FowarderRequest`**:
    - `from`: $POEA$ address
    - `to`: transaction recipient contract address
    - `value`: native token value required.
    - `gas`: gas price
    - `nonce`: $POEA$ nonce
    - `data`: encoded transaction data which will be executed on the target contract
    - `validUntilTime`: valid limitation time. set to 0 as default.
- **`RelayData`**:
    - `maxFeePerGas`: maximum fee per gas price
    - `maxPriorityFeePerGas`: maximum priority fee per gas price
    - `transactionCalldataGasUsed`: max gas used to make the transaction call
    - `relayWorker`: relay worker address
    - `paymaster`: paymaster contract address
    - `forwarder`: forwarder contract address
    - `paymasterData`: uniswap v3 pair address for token (Silent/WETH)
    - `clientId`: client ID. set to 1 as default

#### Events:
- **`TransactionRelayed`**: Emitted when a transaction is relayed. **Note** that the actual internal function call might be reverted.
    - `relayManager`: relay manager address
    - `relayWorker`: relay worker address
    - `relayRequestID`: relay request unique ID
    - `from`: $POEA$ address
    - `to`: transaction recipient contract address
    - `paymaster`: paymaster contract address
    - `selector`: relay call function selector
    - `status`: code describing all possible failure reasons reported or if the transaction was successful
    - `charge`: relay request charge / fee deducted from paymaster

### Paymaster
For ease of understanding, this portion only focuses describing the core Paymaster functionalities without crosschain (as if the Paymaster were all on one chain). Discussions about the Paymaster contract's crosschain attritubes can be found in the intention document.

#### Functions:
- **`preRelayedCall`**
    Invoked from `RelayHub` contract before the transaction executed on `Forwarder` contract.
    
    Checks if the `Paymaster` contract has enough Silent token balance to pay max estimated gas price.

    - params:
        - `relayRequest`: the full relay request structure
        - `signature`: $POEA$ EIP712-compatible signature of the `relayRequest`
        - `approvalData`: extra dapp-specific data
        - `maxPossibleGas`: maximum possible amount of gas the user may be charged for
    - returns:
        - `context`: byte array to be passed to postRelayedCall containing information about token used to charge user
        - `revertOnRecipientRevert`: flag that indicates whether `Paymaster` contract has enough balance to pay max estimated gas price. `true` if `Paymaster` can pay, `false` if not
    
- **`postRelayedCall`**
    Invoked from `RelayHub` contract after the transaction executed on `Forwarder` contract.
    
    Calculates the actual gas price used for executing relay transaction in `Forwarder` contract and deposits the equivalent amount in Silent tokens to `RelayHub` contract by calling `depositProceedsToHub` internally.
    
    - params:
        - `context`: the call context, as returned by the preRelayedCall
        - `success`: `true` if the relayed call succeeded, `false` if it reverted
        - `gasUseWithoutPost`: actual amount of gas used by the entire transaction, **minus** the gas used by the postRelayedCall itself.
        - `relayData`: the relay params of the request
    - returns:
        - byte array about token and actual token charges to the user
        - boolean indicating successful transaction
    
- **`depositProceedsToHub`**
    Deposits the relayed transaction fee/cost in Silent tokens to the `RelayHub` contract
    
    - params:
        - `charge`: Silent token equivalent paid by relayer as gas to submit transaction on behalf of the user

- **`deposit`**
    Deposits ERC20 tokens into `Paymaster` contract. 
    Sender must approve `Paymaster` contract to move funds before using this call. 
    ERC20 token being deposited must also be approved by the `Paymaster` contract before using this call.
    
    Emits a `PaymasterDeposited` event.

    - params:
        - `_token`: address of ERC20 token
        - `_amount`: transfer amount of tokens
    
- **`depositEth`**
    Deposits ERC20 tokens into `Paymaster` contract using the deployed chain's native token. 
    
    5% of the eth will be charged as a deposit fee and it will be transferred to `FEE_MANAGER` registered in `Paymaster` contract. 
    
    The remaining 95% of ETH will be swaped into Silent tokens using the `UniSwap V3` router within the stipulated `_deadline` and deposited into `Paymaster` contract.
    
    Emits a `PaymasterDeposited` event.
    
    - params 
        - `_deadline`: Deadline for the swap transaction
    
- **`withdrawToken`**
    Withdraws Silent tokens from `Paymaster` contract.
    
    A withdrawal fee will be charged and  transfered to `ETH_MANAGER` account whiles the remaining amount will be withdrawn to `_receipient` address.
    
    Can only be called by the $PEOA$. Thus, users will not be able to withdraw funds directly from the `Paymaster` contract.
    
    Emits a `PaymasterWithdrawn` event.

    - params:
        - `_receipient`: address of account recevier
        - `_token`: address of Silent token
        - `_amount`: amount of `_token`

- **`withdrawTokenWithSig`**
    Withdraws Silent tokens from `Paymaster` contract using the Paymaster's signature.
    
    A withdrawal fee will be charged and  transfered to `ETH_MANAGER` account whiles the remaining amount will be withdrawn to `_receipient` address.
    
    Allows users to withdraw funds directly from the `Paymaster` contract. An alternative to 
    
    Emits a `PaymasterWithdrawn` event.

    - params:
        - `_receipient`: address of account recevier
        - `_token`: address of Silent token
        - `_amount`: amount of `_token`
        - `_signature`: signature from $POEA$
        - `_nonce`: nonce from $POEA$

#### Types (Struct):
- **`GasAndDataLimits`**: The limits the `Paymaster` allows to be imposed by the `RelayHub` on user input
    - `acceptanceBudget`: threshold which binds `Paymaster` to refund gas whether transaction succeeds or reverts. If the transaction consumes more than `acceptanceBudget` the `Paymaster` will be charged for gas no matter what
    - `preRelayedCallGasLimit`: max gas usage of `preRelayedCall`
    - `postRelayedCallGasLimit`: max gas usage of `postRelayedCall`
    - `calldataSizeLimit`: max length of data being sent

#### Events:
- **`PaymasterDeposited`**: Emitted when a user makes a deposit
    - `_token`: address of Silent token deposited
    - `_sender`: address of account sender
    - `_amount`: amount of `_token`
    - `_timestamp`: timestamp of transaction

- **`PaymasterWithdrawn`**: Emitted when a user makes a withdrawal
    - `_token`: address of the Silent token
    - `_recepient`: address of account recevier
    - `_amount`: amount of `_token`
    - `_timestamp`: timestamp of transaction

## Running and Registering a Relay Server

Silent users need access to relayers to send their messages to the blockchain to annonymously access decentralized Applications (dApps). Any Silent user can access any available relayers to communicate with any supported dApp.

Relay Servers get reimbursed by Paymasters for the gas they spend sending transactions for users, plus a transaction fee that is defined by the protocol.

This article section explains:
- How to run a relay server on a cloud virtual machine (VM) using Google Cloud Platform Compute, though your can use any other hosting provider
- How register and become a relayer on the Silent Protocol through `Renode Staking`

### Directions to Run a Relay Server
Infrastructure needed to deploy and run a relay server.

#### Requirements
- A Relay Server Virtual Machine with docker installed and a publicly accessible static IP address
- A DNS service (such as GoDaddy, NameCheap, or DuckDNS) to give your host a DNS name
- For technical assistance, please use our discord channel (add link)

#### Intial Setup
Set up a virtual machine (VM) that will run the relay server.

1. Go the the [GCP Console](https://console.cloud.google.com/compute/instances)
2. Click **CREATE INSTANCE**.
3. Set these parameters (accept the default for all the others):
    | Heading               | Parameter              | Value                    |
    | --------------------- | ---------------------- | ------------------------ |
    | Name                  |                        | Select a meaningful name |
    | Machine Configuration | Machine Type           | e2-micro                 |
    | Boot Disk             | Container Optimized OS | Selected                 |
    | Firewall              | Allow HTTPS traffic    | Selected                 |
    | Firewall              | Allow HTTP traffic    | Selected                 |
4. Click **Create**
5. Obtain a DNS entry from a registrar service. Some major DNS services are: [Namecheap](https://www.namecheap.com/) and [GoDaddy](https://www.godaddy.com/)
6. Configure the external IP of the VM in the DNS by adding an "A" record for that IP in your DNS service. Note: by default, public IP is "ephemeral" and might change after reboot.

#### Docker Container
Now that the VM is running and has a DNS entry, the next step is to actually run the relay software. It runs inside a docker container and will be deployed using docker-compose.

1. SSH into the relayer VM
2. Download the relayer configuration files 
    The `docker-compose.yml` and `.env` files must be placed in the root folder.
    ```
    curl https://raw.githubusercontent.com/Silent-Protocol/relayer-service/main/docker-compose.yml > docker-compose.yml
    curl https://raw.githubusercontent.com/Silent-Protocol/relayer-service/main/.env.example > .env
    ```
3. Setup environment variables by editing `.env` file
    | Variable | Example value | Comment |
    | -------- | -------- | -------- |
    | CHAIN_ID| 1| 1 for mainnet, 100 for xDai|
    | PRIVATE_KEY|542pvt5793key129833 | Private key for relayer address without the **0x** prefix|
    | VIRTUAL_HOST|my.hostname.com| Domain name pointing to your relayer ip address|
    | LETSENCRYPT_HOST|my.hostname.com|Domain name pointing to your relayer ip address|
    | RPC_URL|https://ropsten.infura.io/v3/myKey |URL to a node on the network you wish to use|
    | SERVICE_FEE| 1|Fee in % that is used for service fees|
    | CONFIRMATIONS| Default: 12|Number of block confirmations to wait for before processing an event. Not recommended to set less than 3|
    | MAX_GAS_PRICE| Default: 1000000000|Maximum amount of gwei for relayer's transaction|
4. Download and run the docker images
    ```
    docker-compose up -d
    ```
5. When you see this line it means the setup is done. You can close the SSH window.
    ```
    something done.
    ```

 
### Renode Staking and Registration
In order to serve as a relayer on the Silent network and be whitelisted on the client frontend, relay managers must register with the `RelayHub` through a process called **Renode Staking**. This process requires user's to:
- Stake a set amount of Silent tokens which enables a potential relayer to mint a particular renode (NFT)
    1. Navigate to the [Silent Renode](https://stage-renode.silentdao.org/renode) page
    2. Select the type of renode you would like to bond (stake)
    3. Complete bonding by depositing the required amount of Silent tokens for the chosen renode
- Stake renode(s) to get whitelisted and accesible by Silent users on the frontend
    1. Navigate to the [Silent Relayer](https://stage-renode.silentdao.org/relayer) page
    2. Click **Run a relayer**
    3. Accept the T&Cs.
    4. Enter your Relayer URL
    5. Enter the address of your relay worker
    6. Select which of your renodes to stake
    7. Complete registration by staking your renode in the `Relay Hub` contract

*Relay worker address must correspond to the account whose `PRIVATE_KEY` was specified in your Relay Server's `env` file.*


After running a relay server and successfully completing registration through `Renode Staking`, relayer managers will be able to earn a part of the protocol rewards in addition to the transaction fees earned from relaying users messages.

To learn more about `Renode Staking`, read the [docs](https://hackmd.io/kiI9UUleQf2ow1LSfAm_Og?view)
