Project

One World
NFTDeFi
15,000 USDC
View results
Submission Details
Severity: medium
Valid

NativeMetaTransaction.sol :: executeMetaTransaction() failed txs are open to replay attacks.

Summary

Failed MetaTransactions can be replayed by an attacker because the nonce remains unchanged, potentially leading to unintended actions against the original MetaTransaction user.

Vulnerability Details

executeMetaTransaction() is implemented as follows:

function executeMetaTransaction(
address userAddress,
bytes memory functionSignature,
bytes32 sigR,
bytes32 sigS,
uint8 sigV
) public payable returns (bytes memory) {
MetaTransaction memory metaTx = MetaTransaction({
nonce: nonces[userAddress],
from: userAddress,
functionSignature: functionSignature
});
require(
verify(userAddress, metaTx, sigR, sigS, sigV),
"Signer and signature do not match"
);
// increase nonce for user (to avoid re-use)
nonces[userAddress] = nonces[userAddress] + 1;
emit MetaTransactionExecuted(
userAddress,
msg.sender,
functionSignature,
hashMetaTransaction(metaTx)
);
// Append userAddress and relayer address at the end to extract it from calling context
(bool success, bytes memory returnData) = address(this).call{value: msg.value}(
abi.encodePacked(functionSignature, userAddress)
);
require(success, "Function call not successful");
return returnData;
}

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

POC

Consider the following scenario:

  • Bob has 1,000 USDC in his wallet.

  1. Bob submits a MetaTransaction to execute joinDAO() to mint an ERC1155 token priced at 1,000 USDC.

  2. Before the MetaTransaction is executed, Bob sends 500 USDC to Alice.

  3. When the MetaTransaction submitted in step 1 executes, it fails due to insufficient funds.

  4. Several days later, Alice sends 500 USDC back to Bob.

  5. 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.

Impact

Actions could be executed unexpectedly against the MetaTransaction original user.

Tools Used

Manual review.

Recommendations

Failed transactions should still increment nonces[userAddress] to prevent future re-execution.

Updates

Lead Judging Commences

0xbrivan2 Lead Judge 12 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Appeal created

0xbrivan2 Lead Judge
12 months ago
0xbrivan2 Lead Judge 11 months ago
Submission Judgement Published
Validated
Assigned finding tags:

failed meta transactions are replayable

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.