Assuming that you are referring to a transaction that was included in previous blocks for a particular chain, you can get the transaction receipt using cast
and decode the transaction data within the test itself (refer here). This coupled with foundry vm.ffi
will give you the test you need.
For Eg :
Here I have shown how to decode a simple ERC20 transfer
transaction using cast within a forge test and then assert the decoded output.
// SPDX-License-Identifier: CAL
pragma solidity =0.8.19;
import {Test, console2} from "forge-std/Test.sol";
import "openzeppelin-contracts/contracts/utils/Strings.sol";
contract TransactionTest is Test {
// Decode transaction calldata with function selector
function extractCalldata(bytes memory calldataWithSelector) internal pure returns (bytes memory) {
bytes memory calldataWithoutSelector;
require(calldataWithSelector.length >= 4);
assembly {
let totalLength := mload(calldataWithSelector)
let targetLength := sub(totalLength, 4)
calldataWithoutSelector := mload(0x40)
// Set the length of callDataWithoutSelector (initial length - 4)
mstore(calldataWithoutSelector, targetLength)
// Mark the memory space taken for callDataWithoutSelector as allocated
mstore(0x40, add(calldataWithoutSelector, add(0x20, targetLength)))
// Process first 32 bytes (we only take the last 28 bytes)
mstore(add(calldataWithoutSelector, 0x20), shl(0x20, mload(add(calldataWithSelector, 0x20))))
// Process all other data by chunks of 32 bytes
for { let i := 0x1C } lt(i, targetLength) { i := add(i, 0x20) } {
mstore(add(add(calldataWithoutSelector, 0x20), i), mload(add(add(calldataWithSelector, 0x20), add(i, 0x04))))
}
}
return calldataWithoutSelector;
}
function testTransaction() public {
// Target Transaction to decode. (IERC20 transfer transaction)
string memory txHash = "0xa88280fd1bedbb83b7e4260cda7c77e747eeacee199259b13607809cbffaeaf5";
// Traget network rpc
string memory rpcUrl = "https://1rpc.io/matic";
// Cast command to get transaction data
string memory castCommand = string.concat("cast tx ", txHash, " --rpc-url ", rpcUrl, " input ");
string[] memory inputs = new string[](3);
inputs[0] = "bash";
inputs[1] = "-c";
inputs[2] = castCommand;
//Exec cast command
bytes memory resultReceipt = vm.ffi(inputs);
//Decode Data
(address to,uint256 amount) = abi.decode(extractCalldata(resultReceipt),(address,uint));
assertEq(to,address(0x5A37E156191Befe6923765E20487Bad0a7057c28));
assertEq(amount,5182246);
}
}