Deploy Contract Using a Relayer

Here's how to deploy smart contracts without risk of exposing a private key by using Defender Relayer API. What is a relayer?

Copy Your Defender Team API Key and Secret

From Defender, select the hamburger menu at the top right and then Team API Keys. Here you will see any existing API keys as well as what can be done with them. From this dashboard you can also delete API keys by hovering over it and selecting the trash can from the right.

Select Create Team API Key, then leave everything checked unless you wish to restrict the rights of what can be performed using this API key. Hit Save. You will be prompted to copy the API key and secret. Store these in a secure location. They will not be displayed again.

Select the checkmark to indicate that you have copied the keys, and select Save.

Copy your team API key and secret from Defender.

Create A Relayer

First, install the necessary package:

$ npm install defender-relay-client

Create a script such as the following, supplying your Defender API key and secret in your .env file and adjusting variable names as appropriate.

const { RelayClient } = require('defender-relay-client');
const { appendFileSync, writeFileSync} = require('fs');

async function run() {
  const { DEFENDER_API_KEY: apiKey, DEFENDER_API_SECRET: apiSecret } = process.env;
  const relayClient = new RelayClient({ apiKey, apiSecret });

  // create relay using defender client
  const requestParams = {
    name: 'MyRelayer',
    network: 'goerli',
    minBalance: BigInt(1e17).toString(),
  const relayer = await relayClient.create(requestParams);
  // store relayer info in file (optional)
  writeFileSync('relay.json', JSON.stringify({
  }, null, 2));
  console.log('Relayer ID: ', relayer);

  // create and save the api key to .env - needed for sending tx
  const {apiKey: relayerKey, secretKey: relayerSecret} = await relayClient.createKey(relayer.relayerId);
  appendFileSync('.env', `\nRELAYER_KEY=${relayerKey}\nRELAYER_SECRET=${relayerSecret}`);

run().catch((error) => {
  process.exitCode = 1;

Note: To send a transaction directly via the Relayer using the API, you need the key and secret (which were appended in the above code to your .env file). If, however, you wish to send a transaction by way of an Autotask, the only credentials you need are the team API key and secret along with the relayerId (which in the above step was saved to the relay.json file).

Compile and Deploy the Contract

Run npx hardhat compile (or the equivalent if using a different compiler) to get your smart contract ready for deployment.

Use the following script to deploy the contract:

const { DefenderRelayProvider, DefenderRelaySigner } = require('defender-relay-client/lib/ethers');
const { ethers } = require('hardhat');
const {writeFileSync} = require('fs');

async function main() {
  const credentials = {apiKey: process.env.RELAYER_KEY, apiSecret: process.env.RELAYER_SECRET};
  const provider = new DefenderRelayProvider(credentials);
  const relaySigner = new DefenderRelaySigner(credentials, provider, { speed: 'fast' });
  const MyContract = await ethers.getContractFactory("SimpleRegistry");
  const myContract = await MyContract.connect(relaySigner).deploy().then(f => f.deployed());

  writeFileSync('deploy.json', JSON.stringify({
    MyContract: myContract.address,
  }, null, 2));

  console.log(`MyContract: ${myContract.address}\n`);

if (require.main === module) {
  main().then(() => process.exit(0))
    .catch(error => { console.error(error); process.exit(1); });

This code pulls the Relayer's credentials from the local file along with the artifacts for the contract and uses ethers.js to deploy. The relevant address of the contract is saved to the local file deploy.json.

Congratulations on successfully deploying your contract via Relayer!


Can relayers be used to deploy upgradable contracts too?

Thank you @slw.eth, works like a charm!

I am curious how we can integrate this in a hardhat based deployment that also verification of a contract on Etherscan would be possible.
Could someone provide some advice here pls?

Hi @slw.eth, thanks for the tutorial! How to pass parameters to the deploy function, including a minimalforwarder for example? Thanks