Summary
NativeMetaTransaction::executeMetaTransaction()
transactions are very likely to revert due to not appending relayer address at the end of functionSignature
.
Vulnerability Details
The NativeMetaTransaction::executeMetaTransaction
function when executing, makes a call to a function given via its functionSignature
argument. About that call, the documentation in code comments stipulates this:
However, while userAddress
is appended at the end of functionSignature
, the relayer address is not.
File: /contracts/meta-transaction/NativeMetaTransaction.sol#L33-L68
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"
);
nonces[userAddress] = nonces[userAddress] + 1;
emit MetaTransactionExecuted(
userAddress,
msg.sender,
functionSignature,
hashMetaTransaction(metaTx)
);
(bool success, bytes memory returnData) = address(this).call{value: msg.value}(
@--> abi.encodePacked(functionSignature, userAddress)
);
require(success, "Function call not successful");
return returnData;
}
This can lead to a failling extraction in the calling context and makes the transaction revert.
Impact
NativeMetaTransaction::executeMetaTransaction() transactions are very likely to revert.
Tools Used
Manual review.
Recommendations
Append the relayer address at the end of functionSignature
as specified in the documentation.
File: /contracts/meta-transaction/NativeMetaTransaction.sol#L33-L68
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)
++ abi.encodePacked(functionSignature, userAddress, msg.sender)
);
require(success, "Function call not successful");
return returnData;
}