Skip to main content
The RelayAdapter pattern is how the ShieldedPool composes with utilities that themselves live in public contract space. It allows a user with a shielded position to interact with a public contract (swap on a DEX, lend into a lending market, settle a payment) and have the output of that interaction return to the ShieldedPool, all in a single atomic transaction. The user’s identity is not revealed to the public contract; the utility sees a generic adapter, not a specific user address. Z Trade and Z Lend both integrate the RelayAdapter pattern. Third-party utilities can also integrate it; the pattern is extensible.

What a RelayAdapter does

A RelayAdapter is a contract that sits between the ShieldedPool and a target utility contract. The adapter has three jobs:
  1. Unshield. Take shielded inputs from the ShieldedPool. The user proves ownership of the inputs in zero-knowledge as part of the same transaction.
  2. Execute. Call the target utility contract with the unshielded inputs. The utility contract sees a normal-looking call from the adapter; it has no view of who the user is.
  3. Reshield. Take whatever the utility returns and reshield it back into the ShieldedPool. The output becomes a new note belonging to the user.
All three steps happen in a single atomic transaction. If any step fails, the entire transaction reverts and the user’s shielded balance is unchanged.

What an observer sees

An on-chain observer watching a RelayAdapter transaction sees:
  • A call from the user’s wallet (or from a Broadcaster on the user’s behalf) into the adapter.
  • The adapter calling the target utility.
  • The utility returning.
  • The adapter creating new ShieldedPool commitments.
What the observer does not see:
  • Which shielded notes were spent.
  • The amount of the underlying interaction.
  • The user’s other shielded balances or history.
The utility contract sees the adapter as the caller. It does not see the user.

Parameter binding

A critical security property of the RelayAdapter pattern is that the parameters of the utility call are bound into the user’s zero-knowledge proof. The user proves not just “I own these shielded inputs” but “I authorize this specific call to this specific utility with these specific parameters.” A malicious Broadcaster (or any intermediary) cannot substitute a different call without invalidating the proof. This is what makes Broadcaster relay safe. The Broadcaster pays gas and submits the transaction but cannot alter what is being done.

Broadcaster role

The Broadcaster is an off-chain agent that submits RelayAdapter transactions on behalf of users. The Broadcaster’s job is to make the user-experience smooth: the user does not need to hold native gas tokens on the host chain, does not need to manage transaction nonces, and is not the on-chain originator of the transaction (which would partially deanonymize them by linking their wallet to the transaction). The Broadcaster is paid a per-slot fee from inside the shielded transaction. The fee comes out of the user’s shielded balance, not from the user’s external wallet. Multiple Broadcasters can serve the network in parallel. Users can choose which Broadcaster to use, or run their own.

Extending to new utilities

A new utility can integrate the RelayAdapter pattern by:
  1. Deploying its contract on the host EVM chain.
  2. Configuring a RelayAdapter that knows how to unshield the relevant assets, call the utility, and reshield the outputs.
  3. Optionally working with Broadcasters to ensure relay coverage.
The contract itself does not need to know about the ShieldedPool. It receives normal ERC-20 calls from the adapter and returns normal ERC-20 outputs. The privacy work happens entirely in the adapter and in the user’s proof. See Build on Z → ShieldedPool integration for a worked integration walkthrough.