Skip to content

Instantly share code, notes, and snippets.

@cmdzro
Last active November 9, 2021 13:36
Show Gist options
  • Save cmdzro/0547725ca6faa2067e7edf3c70b697f1 to your computer and use it in GitHub Desktop.
Save cmdzro/0547725ca6faa2067e7edf3c70b697f1 to your computer and use it in GitHub Desktop.
Send erc20 token transfer transaction to gnosis safe
import { run, ethers } from "hardhat"
import Safe, { SafeTransactionOptionalProps } from "@gnosis.pm/safe-core-sdk"
import { EthersAdapter } from "@gnosis.pm/safe-core-sdk"
import { MetaTransactionData } from '@gnosis.pm/safe-core-sdk-types'
const safeAddress = "0xfA64EE..." // on rinkeby testnet
const tokenAddress = "0x18B225..." // on rinkeby testnet
const TokenFactory = await ethers.getContractFactory("TokenContract")
const token = TokenFactory.attach(tokenAddress)
const [owner] = await ethers.getSigners()
const ethAdapter = new EthersAdapter({
ethers,
signer: owner
})
const safeSdk = await Safe.create({ ethAdapter, safeAddress })
const safe = await safeSdk.connect({ ethAdapter, safeAddress })
const unsignedTransaction = await token.populateTransaction.transfer("0x5d07C6...", 100)
console.log(unsignedTransaction)
const transactions: MetaTransactionData[] = [{
to: tokenAddress,
value: "0",
data: unsignedTransaction.data!
}]
const safeTransaction = await safe.createTransaction(transactions)
console.log(safeTransaction) // returns with a different "to" than specified in line 27
const owner1Signature = await safe.signTransaction(safeTransaction)
console.log(`owner signature: ${owner1Signature}`) // returns undefined
@DmitryBespalov
Copy link

the lines 24-27 does not look right to me, I think what you need is just to encode data, and not serialize the whole transaction.

so, you would just use data: unsignedTransaction.data on line 32

@cmdzro
Copy link
Author

cmdzro commented Nov 8, 2021

Thx @DmitryBespalov , I changed it but still get the same output:

{
  data: '0xa9059cbb000000000000000000000000e5b0bfc7f8c489837aded29b8f80ff08bb1a65570000000000000000000000000000000000000000000000000000000000000064',
  to: '0x18B225...',
  from: '0x5d07C6...'
}
EthSafeTransaction {
  signatures: Map(0) {},
  data: {
    to: '0x8D29bE...', <-- this one I don't know where it's coming from
    value: '0',
    data: '0x8d80ff0a000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000990018b225088139f85fa8c2ad26bc6f22a1b535545300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044a9059cbb000000000000000000000000e5b0bfc7f8c489837aded29b8f80ff08bb1a6557000000000000000000000000000000000000000000000000000000000000006400000000000000',
    operation: 1,
    baseGas: 0,
    gasPrice: 0,
    gasToken: '0x0000000000000000000000000000000000000000',
    refundReceiver: '0x0000000000000000000000000000000000000000',
    nonce: 8,
    safeTxGas: 0
  }
}
owner signature: undefined

@cmdzro
Copy link
Author

cmdzro commented Nov 8, 2021

(I updated the code accordingly and also included parts of the addresses to better understand what goes in and out)

@rmeissner
Copy link

rmeissner commented Nov 8, 2021

The sdk is encoding your array of txs (which contains 1 tx) into a multisend. The to is the address of the multisend contract (see https://github.com/gnosis/safe-deployments/blob/main/src/assets/v1.1.1/multi_send.json#L7)

To avoid the usage of multisend, you should not use an array, but just the single tx, as the parameter for createTransaction

@cmdzro
Copy link
Author

cmdzro commented Nov 8, 2021

Ah that's actually ok then as I want to have multiple transaction to be batched (this is just a first quick test). Thx for the explanation @rmeissner 👍

So then why does it not show up in the gnosis frontend yet? And why is it not getting signed? Any idea? Thx!

@germartinez
Copy link

germartinez commented Nov 8, 2021

Hi @cmdzro, to display the transaction in the web interface you should use the Safe Service Client package inside the Safe Core SDK Monorepo. This package allows to comunicate with our Safe Transaction Service to collect signatures offchain.

These should be the steps to follow:

As a side note:
Line 20 is not needed. It would only be useful to connect the sdk to a different Safe account or to connect another signer to the same Safe account (o another signer to another Safe account).

@cmdzro
Copy link
Author

cmdzro commented Nov 9, 2021

Thx a lot for your help @germartinez , greatly appreciated 🤗 ... I'll read up on all this and get back if I have further questions.

You are all very supportive ❤️ – Thx again!

@cmdzro
Copy link
Author

cmdzro commented Nov 9, 2021

Quick update: I got it to work 🎉 thx @germartinez @rmeissner and @DmitryBespalov!

I'll try to write something up to have others also benefitting from my learnings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment