foundry
foundry copied to clipboard
feat(`cheatcode`): add `vm.waitForTransaction` for getting tx and receipt info in scripts
Component
Forge
Describe the feature you would like
Problems
First problem: In scripts, there's a frontrunning footgun you have to be careful of. Here's an example with pseudocode:
- Transaction 1: Call
gnosisSafeFactory.createSafe()
to deploy a safe with CREATE (so contract nonce matters) - Transaction 2: Transfer 10 DAI to the safe
Forge will simulate tx1, get the address of the safe, and send tokens to that in tx2. But if someone else deploys a gnosis safe in between, the address of your safe changes and you send tokens to the wrong address. I've encountered this on mainnet, so it's not just theoretical 🙂
(Note that an alternative solution to the first problem is to have --slow
wait for the tx to be mined, then requery for all data before the next transaction)
Second problem: The default broadcast artifacts are not ideal for everyone. For example, if you have upgradeable contracts, you may want <latest-ContractX>.json
for all your contract deploys, instead of one JSON file for each script execution. This is doable by using the file writing cheats within a script, but currently you can't access tx and receipt info so you have more limited logging capabilities than forge itself.
Solution
function waitForTransaction() external returns (Tx memory tx, Receipt memory receipt);
(or if ethers-rs has a function of the same purpose with a different name, the cheatcode can match that name)
This cheatcode can be called after each broadcasted transaction. It will wait for the transaction to be mined, return the tx and receipt data, then continue.
One issue here is the returned structs will differ depending on if the tx is type 0, 1, or 2. As a result we probably need to just return bytes memory
for both tx
and receipt
, and use the existing JSON helper structs with forge-std methods to help decode the transactions, which is ok.
One other issue is that this is the first cheatcode that would be "script only", i.e. this wouldn't make much sense in tests, though I guess it could work there too but for all transactions?
Additional context
No response