2

I have a problem with creating a custom transaction proposal.
Here is my code:

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'
});

// 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!!!!');

But when i try to run this code with ts-node i get an error:

Error: Unprocessable Entity
    at sendRequest (/home/msolovyev/crypto-projects/safe-test/node_modules/@safe-global/api-kit/src/utils/httpRequests.ts:58:9)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async proposeBurnFromMultisig (/home/msolovyev/crypto-projects/safe-test/src/multisigs.ts:96:5)

Please tell me how to correctly calculate the value of the data property for a transaction?

1 Answer 1

2

There is a few things that might cause your problem, an incorrect transaction data or an incorrect environment setup, first verify that safeAddress and tokenAddress are correct, then check that the ABI you are using is correct for the ERC-20 token you are interacting with, get more detailed error by replacing this

await safeService.proposeTransaction({
    safeAddress,
    safeTransactionData: safeTransaction.data,
    safeTxHash,
    senderAddress: await signerOrProvider.getAddress(),
    senderSignature: senderSignature.data
}); 

by this

try {
    await safeService.proposeTransaction({
        safeAddress,
        safeTransactionData: safeTransaction.data,
        safeTxHash,
        senderAddress: await signerOrProvider.getAddress(),
        senderSignature: senderSignature.data
    });
} catch (error) {
    console.error("Error while proposing transaction:", error.response ? error.response.data : error.message);
}

you can also check your local Gnosis Safe Transaction Service and that it is reachable at http://localhost:8000 check also that your API key and secret are valid.

edit: the error Error while proposing transaction: Unprocessable Entity mean the API request you are making contains malformed data or is missing required fields, lets debug further, check API_KEY and API_SECRET are being loaded correctly

console.log('API Key:', API_KEY);
console.log('API Secret:', API_SECRET);

also

console.log('Safe Address:', safeAddress);
console.log('Token Address:', tokenAddress);

be sure that there is no incorrect or missing information, if that persist reach out to Gnosis Safe team for assistance

6
  • Thanks for the answer! However, it didn't work for me. Tx service is available, safeAddress and tokenAddress is correct. ABI is correct. The error message is: Error while proposing transaction: Unprocessable Entity Apr 18, 2023 at 11:53
  • I updated my answer
    – Saxtheowl
    Apr 18, 2023 at 12:13
  • All parameters are filled, the request goes to the service, but come back with 422 error: { size: 0, timeout: 0, [Symbol(Response internals)]: { url: 'localhost:8000/txs/api/v1/safes/…', status: 422, statusText: 'Unprocessable Entity', headers: Headers { [Symbol(map)]: [Object: null prototype] }, counter: 0 } } Apr 18, 2023 at 13:04
  • there is still an issue with the data being sent in the API request
    – Saxtheowl
    Apr 18, 2023 at 18:35
  • I found out that the problem is in the defender signer. If you use the code, javascript const provider = new ethers.providers.JsonRpcProvider(RPC_URL); const signerOrProvider = new ethers.Wallet(DEVELOPER_WALLET_KEY!, provider); then everything works. So, I have to go to OpenZeppelin) Apr 19, 2023 at 9:50

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.