I know that an ERC-20 approve method has only 2 parameters: sender and amount. I'd like to get an extra hash recorded on chain with the approval, so I can test it later when coming to process transferFrom requests.

Ideally, my flow would be: user reads description on page, telling them they're about to approve n tokens for purpose X. When they click a button, MetaMask pops up, and shows them a message saying "you're approving n of token t with data X". Later on, I can find the approval transaction, and get "X" from it.

Is there a way to include extra information with the transaction - without writing an external smart contract?

2 Answers 2


You can use ethers to encode the transfer or approve function's data then append your memo to that data.

The data will be more than the transfer function needs but luckily EVM will ignore the extra data kinda the point of why all function arguments are zero-padded.

Keep in mind you have to encode data your self and also decode the data your self from the other side.

Here is a quick example

import ethers from "ethers"

// Example ERC-20 contract address and ABI (replace with your actual contract details)
const contractAddress = '0xYourContractAddress';
const contractAbi = [...];  // Replace with your ERC-20 ABI

const provider =  {} // replace with your provider
const signer = {} // replace with your signer

// Your ERC-20 contract instance
const contract = new ethers.Contract(contractAddress, contractAbi, provider);

// Recipient address and amount to transfer
const toAddress = '0xRecipientAddress';
const amount = 100n; // replace with the amount you want to transfer

const data = contract.interface.encodeFunctionData('transfer', [toAddress, amount]);

const memo = ethers.hexlify(ethers.toUtf8Bytes("Hello memo"));

const transaction = {
  to: await token.getAddress(),
  // we need to slice the memo to remove 0x before appending
  data: data + memo.slice(2),

const tx = await signer.sendTransaction(transaction);

// somewhere else you can get the transaction 
const tx = provider.getTransaction(txHash)

// 0x + function selector 4bytes-8chars + 2 32bytes arguments = 138 
const hexMemo = tx.data.substring(138, tx.data.length);

const memoString = ethers.toUtf8String("0x" + txMemo1);


You can usually add data to any transaction, so you can add some message converted to bytes to send a message onchain.

Look into this

Hope this helps!

  • Correct me if I'm wrong, but this shows how to add data to a blockchain in a transaction - but I need it to be part of an ERC-20 approve transaction. Nov 4, 2022 at 22:01
  • As you said, approve only takes 2 args, so you can't add a message in the arguments. But you can add extra data to your approve call (i.e. your message like shown in the link I shared), so that would be part of the approve transaction Nov 4, 2022 at 22:44
  • How exactly? The link you specified shows how to create a tx that contains a hash manually, using MyEtherWallet, I need code that does it with an actual approve tx. Nov 5, 2022 at 0:35

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.