I am using https://github.com/gnosis/ethers-multisend to encode batch transactions into Meta transactions. And following https://docs.gnosis-safe.io/tutorials/tutorial_tx_service_initiate_sign to send my encoded transaction to gnosis. The transactions get encoded but I get the following error. Can anyone help me how to submit transactions to gnosis transaction service? enter image description here

Following is the code snippet that I am using

import { encodeMulti, encodeSingle, MetaTransaction } from 'ethers-multisend'

const [transactions, setTransactions] = useState<MetaTransaction[]>([])

const addToBatch = () => {
      const encodedTx = encodeSingle({
            type: TransactionType.transferFunds,
            id: '1',
            token: tokenAddress,
            to: recipientAddress,
            amount: ethers.utils.parseUnits(fundAmount, decimals).toString(),
            decimals: decimals,

if(!transactions) {
} else {
    console.log('transactions', transactions)
    setTransactions([...transactions, encodedTx])

const executeTransaction = () => {
    const encodedMultiTransactions = encodeMulti(transactions)
    submitTx(accountData?.address, accountData?.address, PRIVATE_KEY, encodedMultiTransactions)
const submitTx = async(safe, sender, privateKey, tx) => {

    const safeDomain = new EIP712Domain({
        verifyingContract: safe,

    const SafeTx = safeDomain.createType('SafeTx', [
        { type: 'address', name: 'to' },
        { type: 'uint256', name: 'value' },
        { type: 'bytes', name: 'data' },
        { type: 'uint8', name: 'operation' },
        { type: 'uint256', name: 'safeTxGas' },
        { type: 'uint256', name: 'baseGas' },
        { type: 'uint256', name: 'gasPrice' },
        { type: 'address', name: 'gasToken' },
        { type: 'address', name: 'refundReceiver' },
        { type: 'uint256', name: 'nonce' },

    tx['operation'] = 1
    const baseTxn = tx

    console.log(JSON.stringify({ baseTxn }))

    // Let the Safe service estimate the tx and retrieve the nonce
    const { safeTxGas, lastUsedNonce } = await gnosisEstimateTransaction(

    const txn = {
        // Here we can also set any custom nonce
        nonce: lastUsedNonce === undefined ? 0 : lastUsedNonce + 1,
        // We don't want to use the refund logic of the safe to lets use the default values
        baseGas: 0,
        gasPrice: 0,
        gasToken: '0x0000000000000000000000000000000000000000',
        refundReceiver: '0x0000000000000000000000000000000000000000',

    console.log({ txn })
    const safeTx = new SafeTx({
        data: utils.arrayify(txn.data)
    const signer = async data => {
        const { r, s, v } = ethUtil.ecsign(data, ethUtil.toBuffer(privateKey))
        return ethUtil.toRpcSig(v, r, s)

    const signature = await safeTx.sign(signer)

    console.log({ signature })

    const toSend = {
        contractTransactionHash: '0x' + safeTx.signHash().toString('hex'),
        signature: signature,

    console.log(JSON.stringify({ toSend }))

    const { data } = await gnosisProposeTx(safe, toSend)
    console.log({ data })

safe: "0x7723d6CD277F0670fcB84eA8E9Efe14f1b16acBB"

1 Answer 1


The tutorial you link is for the Safe transaction service, but you interact with the Safe relay service.

These are different services and the Safe relay service is not actively maintained.

If you want to interact with the Safe transaction service you can find here a list of available networks.

Note: This will probably still not solve the issue. It might be that your multisend call reverts. To better debug this could you share the data and Safe address from the first screenshot?

  • I changed the relay service to transaction service https://safe-transaction.rinkeby.gnosis.io/api/v1/safes/${safe}/multisig-transactions/estimations/ and still getting the same error
    – Sweta Shaw
    Aug 11, 2022 at 21:56
  • Added data and safe in the question above since the comment does not support characters that long
    – Sweta Shaw
    Aug 11, 2022 at 22:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.