Since shielder is just a smart contract on Aleph Zero, each transaction in shielder must be submitted by some AccountId on Aleph Zero. However, if this was done just by the user itself, then it would lead to privacy loss. For this reason we introduce relayers: parties that post shielder transactions to chain, on behalf of normal users.

To support relayers we enrich Operations for which it makes sense with two new fields: relayer_address and relayer_fee. Consider the example of the WithdrawETH operation

struct WithdrawETH {
    relayer_address: AccountId,
    relayer_fee: u128,
    withdraw_address: AccountId,
    amount_eth: u128,

Now the corresponding methods would be implemented as follows:

fn update(acc: Account, op: WithdrawETH) -> Account {
    decrease balance of AZERO in acc by op.relayer_fee
    decrease balance of ETH in acc by op.amount_eth
    return acc;

The corresponding implementation of public_exec is

fn public_exec(op: WithdrawETH) {
    transfer op.relayer_fee AZERO from shielder to op.relayer_address
    transfer op.amount_eth ETH from shielder to op.withdraw_address

The typical flow of sending a transaction by the user would be then:

  • Contact a relayer and negotiate fee.

  • Create a transaction placing the relayer's address in relayer_address field and the negotiated fee in relayer_fee (in AZERO). Generate the corresponding snark proof. Note that withdraw_address should be a fresh account with no history, for max privacy.

  • Pass all the data to the relayer.

  • The relayer validates that the relayer_address and relayer_fee is correct, and simulates the transaction to make sure it passes (the proof is correct etc.).

  • The relayer sends the transaction, bears it's gas fee, but gains relayer_fee which should be larger than gas cost.

Last updated