# Problems with the interaction between the relayer and the multisig wallet

**URL:** <https://forum.openzeppelin.com/t/problems-with-the-interaction-between-the-relayer-and-the-multisig-wallet/35683>\
**Category:** Defender\
**Tags:** multisig\
**Created:** [April 11, 2023, 5:40pm UTC](https://forum.openzeppelin.com/t/problems-with-the-interaction-between-the-relayer-and-the-multisig-wallet/35683 "2023-04-11T17:40:32Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Separator](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/separator/32/17822_2.png) [@Separator](https://forum.openzeppelin.com/u/Separator)\
**Post date:** [April 11, 2023, 5:40pm UTC](https://forum.openzeppelin.com/t/problems-with-the-interaction-between-the-relayer-and-the-multisig-wallet/35683/1 "2023-04-11T17:40:32Z")

</div>

Hello OpenZeppelin community!  
Im trying to create an transaction proposal to burn some tokens on my multisig wallet through relayer (code below).  
But i find out that core.safe doesnt have save service for Avalanche Fuji (list of available services below)

> **[Available Services](https://docs.safe.global/learn/safe-core/safe-core-api/available-services)**
>
> This pages provides an overview of the available services

But defender somehow creates proposals etc.  
Can anyone suggest how I can create proposals in a different way?

```javascript

const { ethers } = require('ethers');
const {
  DefenderRelayProvider,
  DefenderRelaySigner,
} = require('defender-relay-client/lib/ethers');
const Safe = require('@safe-global/safe-core-sdk').default;
const EthersAdapter = require('@safe-global/safe-ethers-lib').default;
const SafeServiceClient = require('@safe-global/safe-service-client').default;

const CONTRACT_ADDRESS = '0xFAA27935213A149c5f81442C30BaaD36b15863A9';
const USER_WALLET_ADDRESS = '0x663653284888bf19d7ed0d5b76c9f6f6217fd0b7';
const AMOUNT_TO_BURN = ethers.utils.parseUnits('100', 18);

const API_KEY = 'XXXXX';
const API_SECRET = 'XXXXX';

async function tryToBurnFunds() {
  // Create signer:
  const credentials = { apiKey: API_KEY, apiSecret: API_SECRET };
  const relayerProvider = new DefenderRelayProvider(credentials);
  const signer = new DefenderRelaySigner(credentials, relayerProvider, {
    speed: 'fast',
  });

  // Generate transaction data:
  const burnFunctionHash = ethers.utils.keccak256(
    ethers.utils.toUtf8Bytes('burn(uint256)'),
  );
  const encodedArguments = ethers.utils.defaultAbiCoder.encode(
    ['uint256'],
    [AMOUNT_TO_BURN],
  );
  const transactionData = burnFunctionHash + encodedArguments.slice(2);
  const safeTransactionData = {
    to: CONTRACT_ADDRESS,
    data: transactionData,
    value: 0,
  };

  // Create safe factory:
  const ethAdapter = new EthersAdapter({
    ethers,
    signerOrProvider: signer,
  });
  const safeSdk = await Safe.create({
    ethAdapter,
    safeAddress: USER_WALLET_ADDRESS,
  });
  const safeTransaction = await safeSdk.createTransaction({
    safeTransactionData,
  });

  // Try to send transaction:
  const safeTxHash = await safeSdk.getTransactionHash(safeTransaction);
  const senderSignature = await safeSdk.signTransactionHash(safeTxHash);

// url for Avalanche mainnet is https://safe-transaction-avalanche.safe.global/
  const txServiceUrl = 'HERE MUST BE SAFE SERVICE URL';
  const safeService = new SafeServiceClient({
    txServiceUrl,
    ethAdapter,
  });
  const result = await safeService.proposeTransaction({
    safeAddress: USER_WALLET_ADDRESS,
    safeTransactionData: safeTransaction.data,
    safeTxHash,
    senderAddress: await signer.getAddress(),
    senderSignature: senderSignature.data,
  });

  console.log('result', result);
}

tryToBurnFunds();

```

---

<div class="post-metadata">

**Author:** ![dan\_oz](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/dan_oz/32/17511_2.png) [@dan\_oz](https://forum.openzeppelin.com/u/dan_oz)\
**Post date:** [April 12, 2023, 10:50pm UTC](https://forum.openzeppelin.com/t/problems-with-the-interaction-between-the-relayer-and-the-multisig-wallet/35683/2 "2023-04-12T22:50:04Z")

</div>

If you want to create proposals on a network not supported by Gnosis Safe App, you could use an app such as Defender (there may be other alternatives as well) or interact directly with the Gnosis Safe and provide the appropriate signatures, params, etc. Though this does take some advanced understanding of how to craft the transaction.

---

<div class="post-metadata">

**Author:** ![Separator](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/separator/32/17822_2.png) [@Separator](https://forum.openzeppelin.com/u/Separator)\
**Post date:** [April 19, 2023, 10:37am UTC](https://forum.openzeppelin.com/t/problems-with-the-interaction-between-the-relayer-and-the-multisig-wallet/35683/3 "2023-04-19T10:37:02Z")

</div>

I deployed a safe transaction service locally by [this guide](https://www.youtube.com/watch?v=FUytj_xStDI).  
However, I ran into another problem.  
If i use **DefenderRelaySigner** , the service refuses to accept a request to create an offer and returns a 422 error ( **Error while proposing transaction: Unprocessable Entity** ). Here is my code:

```javascript
import { ethers, utils } from 'ethers';
import SafeApiKit from '@safe-global/api-kit';
import EthersAdapter from '@safe-global/safe-ethers-lib';
import Safe from '@safe-global/safe-core-sdk';
import { SafeTransactionDataPartial } from '@safe-global/safe-core-sdk-types';
import { DefenderRelayProvider, DefenderRelaySigner } from 'defender-relay-client/lib/ethers';

const txServiceUrl = 'http://localhost:8000/txs/';
const safeAddress = '0x512560bB71b98a60bC7e87719D2B8573C935Ff58';
const tokenAddress = '0xFAA27935213A149c5f81442C30BaaD36b15863A9';
const abi = 'erc-20 token abi...';
const amount = '100'; // 100 erc-20 tokens to burn

const {
    API_KEY,
    API_SECRET,
} = process.env;

// Create defender signer:
const credentials = { apiKey: API_KEY!, apiSecret: API_SECRET! };
const relayerProvider = new DefenderRelayProvider(credentials);
const signerOrProvider = new DefenderRelaySigner(credentials, relayerProvider, {
    speed: 'fast'
});
/*
if i use this instead of DefenderRelaySigner, the code will work!!!
const { DEVELOPER_WALLET_KEY, RPC_URL } = process.env;
const provider = new ethers.providers.JsonRpcProvider(RPC_URL);
const signerOrProvider = new ethers.Wallet(DEVELOPER_WALLET_KEY!, provider); */

// Create safeService instance:
const ethAdapter = new EthersAdapter({
    ethers,
    signerOrProvider
});
const safeService = new SafeApiKit({
    txServiceUrl,
    ethAdapter
});

// Create transactoin description:
const contractInterface = new utils.Interface(abi);
const data = contractInterface.encodeFunctionData('burn', [ethers.utils.parseEther(amount)]);

const safeTransactionData: SafeTransactionDataPartial = {
    to: tokenAddress,
    value: '0',
    data,
    operation: 0
};

// Create transaction:
const safeSdk = await Safe.create({
    ethAdapter,
    safeAddress
});
const safeTransaction = await safeSdk.createTransaction({ safeTransactionData });

// Try to propose transaction:
const safeTxHash = await safeSdk.getTransactionHash(safeTransaction);
const senderSignature = await safeSdk.signTransactionHash(safeTxHash);
await safeService.proposeTransaction({
    safeAddress,
    safeTransactionData: safeTransaction.data,
    safeTxHash,
    senderAddress: await signerOrProvider.getAddress(),
    senderSignature: senderSignature.data
});

console.log('DONE!!!!');

```

Has anyone encountered a similar problem?

---

<div class="post-metadata">

**Author:** ![Separator](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/separator/32/17822_2.png) [@Separator](https://forum.openzeppelin.com/u/Separator)\
**Post date:** [April 20, 2023, 11:29am UTC](https://forum.openzeppelin.com/t/problems-with-the-interaction-between-the-relayer-and-the-multisig-wallet/35683/4 "2023-04-20T11:29:31Z")

</div>

The problem was that Defender provides relayer addresses in **non-checksummed** form.  
Safe API requires exactly this [address format](https://help.safe.global/en/articles/4979741-checksummed-address).  
So, if you replace the code with this, then everything works perfectly:

```javascript
import Web3 from 'web3';
import { ethers, utils } from 'ethers';
import SafeApiKit from '@safe-global/api-kit';
import EthersAdapter from '@safe-global/safe-ethers-lib';
import Safe from '@safe-global/safe-core-sdk';
import { SafeTransactionDataPartial } from '@safe-global/safe-core-sdk-types';
import { DefenderRelayProvider, DefenderRelaySigner } from 'defender-relay-client/lib/ethers';

const txServiceUrl = 'http://localhost:8000/txs/';
const safeAddress = '0x512560bB71b98a60bC7e87719D2B8573C935Ff58';
const tokenAddress = '0xFAA27935213A149c5f81442C30BaaD36b15863A9';
const abi = 'erc-20 token abi...';
const amount = '100'; // 100 erc-20 tokens to burn

const {
    API_KEY,
    API_SECRET,
} = process.env;

// Create defender signer:
const credentials = { apiKey: API_KEY!, apiSecret: API_SECRET! };
const relayerProvider = new DefenderRelayProvider(credentials);
const signerOrProvider = new DefenderRelaySigner(credentials, relayerProvider, {
    speed: 'fast'
});

// Convert address to checksummed:
let senderAddress = await signerOrProvider.getAddress();
if (!Web3.utils.checkAddressChecksum(senderAddress)) {
    senderAddress = Web3.utils.toChecksumAddress(senderAddress);
}

// Create safeService instance:
const ethAdapter = new EthersAdapter({
    ethers,
    signerOrProvider
});
const safeService = new SafeApiKit({
    txServiceUrl,
    ethAdapter
});

// Create transactoin description:
const contractInterface = new utils.Interface(abi);
const data = contractInterface.encodeFunctionData('burn', [ethers.utils.parseEther(amount)]);

const safeTransactionData: SafeTransactionDataPartial = {
    to: tokenAddress,
    value: '0',
    data,
    operation: 0
};

// Create transaction:
const safeSdk = await Safe.create({
    ethAdapter,
    safeAddress
});
const safeTransaction = await safeSdk.createTransaction({ safeTransactionData });

// Try to propose transaction:
const safeTxHash = await safeSdk.getTransactionHash(safeTransaction);
const senderSignature = await safeSdk.signTransactionHash(safeTxHash);
await safeService.proposeTransaction({
    safeAddress,
    safeTransactionData: safeTransaction.data,
    safeTxHash,
    senderAddress,
    senderSignature: senderSignature.data
});

console.log('DONE!!!!');

```
