Great thanks @Achal Singh for your answer - https://ethereum.stackexchange.com/a/82318/93117.
Here is a variation:
- for
Hardhat
dev environments
- generalised console.log outputs (rather than looking for specific fields),
- made it for
Ethers 6
- print out the function that was called (if any and if none ... well then I've left it as a reader exercise to fix).
- Loops over list of ABIs you have created in your artifacts folder (you need to create list ... reader exercise to automate this!)
I use a separate calling script parseTransactionCall.sh
so i can pass a transaction as an arg.
NOTE my use of a separate tsconfig.hardhat.json
so i can have contracts and front-end typescript in same project.
parseTransactionCall.sh
:
#!/usr/bin/env sh
npx hardhat --tsconfig tsconfig.hardhat.json vars set TX $1
npx hardhat --tsconfig tsconfig.hardhat.json run scripts/parseTransaction.ts
parseTransaction.ts
:
/*
* Decode information from transaction. Usage:
* - CALL THIS USING parseTransactionCall.sh as it allows passing in TX as argument
* > parseTransactionCall.sh <TX>
* - Add any ABIs to the list at top of script.
*/
import * as JSONbig from "json-bigint";
import {vars} from "hardhat/config";
const { ethers } = require('hardhat');
const abiEvent = require("../src/artifacts/contracts/FunEvent.sol/FunEvent.json");
const abiFun = require("../src/artifacts/contracts/FunTShirts.sol/FunTShirts.json");
const abiNFT = require("../src/artifacts/contracts/FunNFT.sol/FunNFT.json");
type ABIENTRY = {
name: string,
abi: any
}
const abis: ABIENTRY[] = [
{name: "Event", abi: abiEvent},
{name: "Fun", abi: abiFun},
{name: "NFT", abi: abiNFT},
]
const provider = ethers.provider;
const transaction = vars.get("TX") || "0x9c17159774507a669ce1f8a9453998db98bc366555baa62e5b89909c6c8bb582";
console.log(`transaction: ${transaction}`);
(async() => {
const tx = await provider.getTransaction(transaction);
console.log(`transaction tx: ${JSONbig.stringify(tx, null, 2)}`)
if (tx == null) {
return;
}
for (const abiEntry of abis) {
console.log(`TRY ABI: ${abiEntry.name}`)
const interfaceX:any = new ethers.Interface(abiEntry.abi.abi);
const decodedInput = interfaceX.parseTransaction(tx);
if (decodedInput == null) {
console.log(`decodedInput is null so try next`)
continue;
}
console.log(` decodedInput: ${JSONbig.stringify(decodedInput, null, 2)}`);
const abiFn = abiEntry.abi.abi.filter(a => a.name == decodedInput.name);
// Decoded Transaction
console.log(`Decoded Transaction`, {
transaction: transaction,
function_name: decodedInput.name,
fragment: decodedInput.fragment,
from: tx.from,
to: tx.to,
args: decodedInput.args,
erc20Value: Number(decodedInput.value)
});
console.log(`Function from ABI: ${JSONbig.stringify(abiFn, null, 2)}`);
}
})();