Created
July 26, 2025 16:38
-
-
Save bkpleb/071979f0b2a19089f8f4acf40c4368cc to your computer and use it in GitHub Desktop.
decode Alchemy calldata
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { parseAbi, decodeFunctionData } from "viem"; | |
| export interface Execution { | |
| target: string; | |
| value: bigint; | |
| callData: `0x${string}`; | |
| } | |
| // ABI covering all four entry-points | |
| const accountAbi = parseAbi([ | |
| "function execute(address target,uint256 value,bytes data) payable returns (bytes)", | |
| "function executeBatch((address target,uint256 value,bytes data)[] calls) payable returns (bytes[])", | |
| "function executeWithRuntimeValidation(bytes data, bytes authorization) payable returns (bytes)", | |
| // note: paymasterAndData is bytes, not address | |
| "function executeUserOp((address sender,uint256 nonce,bytes initCode,bytes callData,uint256 callGasLimit,uint256 verificationGasLimit,uint256 preVerificationGas,uint256 maxFeePerGas,uint256 maxPriorityFeePerGas,bytes paymasterAndData,bytes signature) userOp,bytes32 aggregator) payable" | |
| ]); | |
| export function decodeAlchemyAccountCall(data: `0x${string}`): Execution[] { | |
| const { functionName, args } = decodeFunctionData({ | |
| abi: accountAbi, | |
| data, | |
| }); | |
| if (!args) { | |
| throw new Error(`Failed to decode function data for ${functionName}`); | |
| } | |
| switch (functionName) { | |
| case "execute": { | |
| const [target, value, callData] = args as [ | |
| string, | |
| bigint, | |
| `0x${string}` | |
| ]; | |
| return [{ target, value, callData }]; | |
| } | |
| case "executeBatch": { | |
| const raw = args[0] as Array<{ | |
| target: string; | |
| value: bigint; | |
| data: `0x${string}`; | |
| }>; | |
| return raw.map(({ target, value, data }) => ({ | |
| target, | |
| value, | |
| callData: data, | |
| })); | |
| } | |
| case "executeWithRuntimeValidation": { | |
| // args[0] is the inner calldata for execute/executeBatch | |
| const innerData = args[0] as `0x${string}`; | |
| // recurse to decode that exactly like a normal call | |
| return decodeAlchemyAccountCall(innerData); | |
| } | |
| case "executeUserOp": { | |
| // args[0] is the PackedUserOperation struct | |
| const userOp = args[0] as Record<string, any>; | |
| const innerData = userOp.callData as `0x${string}`; | |
| return decodeAlchemyAccountCall(innerData); | |
| } | |
| default: | |
| throw new Error(`Unsupported function ${functionName}`); | |
| } | |
| } | |
| const data = "0x34fcd5be0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000120000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044a9059cbb00000000000000000000000040b35800bb3e536aee3dc5dbd46d8f0a39c4dffc000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044a9059cbb00000000000000000000000039008584ef5a94fba2d6d27669429ab47c1fc8e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; | |
| // Decode & print | |
| const calls = decodeAlchemyAccountCall(data as `0x${string}`); | |
| console.log(`Decoded ${calls.length} call(s):`); | |
| calls.forEach((c, i) => { | |
| console.log(`\nCall #${i + 1}`); | |
| console.log(" target: ", c.target); | |
| console.log(" value: ", c.value.toString()); | |
| console.log(" callData:", c.callData); | |
| }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment