Failed MetaTransactions can be replayed by an attacker because the nonce remains unchanged, potentially leading to unintended actions against the original MetaTransaction user.
executeMetaTransaction() is implemented as follows:
Transactions that fail due to dynamic conditions—such as those dependent on external actions or time-sensitive requirements—are not reliable for re-execution at a later time.
In the current setup, if a low-level call fails, the entire transaction is reverted, leaving nonces[userAddress] unmodified. This allows the same transaction to be replayed with the same signature since the nonce has not been incremented.
See also the implementation of OpenZeppelin's MinimalForwarder: Source
Consider the following scenario:
Bob has 1,000 USDC in his wallet.
Bob submits a MetaTransaction to execute joinDAO() to mint an ERC1155 token priced at 1,000 USDC.
Before the MetaTransaction is executed, Bob sends 500 USDC to Alice.
When the MetaTransaction submitted in step 1 executes, it fails due to insufficient funds.
Several days later, Alice sends 500 USDC back to Bob.
An attacker replays the failed MetaTransaction from step 3, and this time it succeeds, depleting Bob's balance without his consent.
Bob's 1,000 USDC is now been spent unexpectedly against him will and can potentially cause fund loss.
Actions could be executed unexpectedly against the MetaTransaction original user.
Manual review.
Failed transactions should still increment nonces[userAddress] to prevent future re-execution.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.