Omniscia Nexera Protocol Audit

BaseTxAuthDataVerifier Manual Review Findings

BaseTxAuthDataVerifier Manual Review Findings

BTA-01M: Incorrect Emittance of Event

Description:

The NexeraIDSignatureVerified event will be emitted even if the signature verification eventually fails.

Impact:

As the impact of this exhibit is off-chain, its severity cannot be quantified above informational.

Example:

sig-gating-contracts/contracts/sigVerifiers/BaseTxAuthDataVerifier.sol
147emit NexeraIDSignatureVerified(
148 block.chainid,
149 userNonce,
150 blockExpiration,
151 address(this),
152 userAddress,
153 argsWithSelector
154);
155
156/// Verify Signature
157if (
158 !SignatureChecker.isValidSignatureNow(
159 _signerAddress,
160 ethSignedMessageHash,
161 _signature
162 )
163) {
164 revert InvalidSignature();
165}
166
167return true;

Recommendation:

We advise it to be emitted after the ensuing if block to prevent off-chain software from triggering when signature validation has failed.

Alleviation:

After discussions with the Nexera Protocol team, we have concluded that the event's emittance prior to an error does not realistically impact its off-chain consumption and that the event should be emitted prior to the SignatureChecker invocation due to potential downstream validations.

As such, we consider this exhibit as nullified given that it describes desirable behaviour.

BTA-02M: Improper Assumption of Calldata

Description:

The BaseTxAuthDataVerifier signature verifier system expects the top-level function call to correctly specify the signature as the last argument of its function and to mutate its function signature to accommodate for the _signature payload.

Both of these assumptions significantly hamper the applicability of the BaseTxAuthDataVerifier due to non-compliancy of EIP function signatures and render it prone to errors, as introducing the signature to any location other than the end of the function's calldata will result in verifications failing.

Additionally, multiple dynamic arguments will be packed in calldata differently, causing the fixed _SIGNATURE_OFFSET reduction to not work with them correctly.

Impact:

The present BaseTxAuthDataVerifier is incompatible with EIPs as it will mutate their function signatures, and is prone to errors if integrators do not properly introduce the bytes memory signature payload as the final argument of their function.

Additionally, the assumption presently introduced will fail to function as expected when multiple dynamic arguments are utilized.

Example:

sig-gating-contracts/contracts/sigVerifiers/BaseTxAuthDataVerifier.sol
97/**
98 * @dev Verifies the authenticity and validity of a transaction's authorization data.
99 * This function checks if the transaction signature is valid, has not expired, and is signed by the correct user.
100 * It also ensures that the transaction has not been replayed by checking and incrementing the nonce.
101 * Emits a {NexeraIDSignatureVerified} event upon successful verification.
102 *
103 * @param msgData The full calldata including the function selector and arguments.
104 * @param userAddress The address of the user who signed the transaction.
105 * @param blockExpiration The block number until which the transaction is considered valid.
106 * @param _signature The signature of the user authorizing the transaction.
107 * @return A boolean value indicating whether the transaction was successfully verified.
108 *
109 * Requirements:
110 * - The current block number must be less than `blockExpiration`.
111 * - The signature must be valid and correspond to `userAddress`.
112 *
113 * Emits a {NexeraIDSignatureVerified} event.
114 */
115function _verifyTxAuthData(
116 bytes calldata msgData,
117 address userAddress,
118 uint256 blockExpiration,
119 bytes memory _signature
120) internal returns (bool) {
121 /// Decompose msgData into the different parts we want
122 bytes calldata argsWithSelector = msgData[:msgData.length -
123 _SIGNATURE_OFFSET];

Recommendation:

We advise the signature payload to be injected instead, permitting data to be extracted efficiently and without mutating the top-level function signatures.

In detail, a low-level assembly block can extract appended calldata that is not necessarily present in the top-level call, permitting EIP-compliant functions to still impose the authentication system designed by the Nexera Protocol.

Alleviation:

After extensive deliberation by the Nexera Protocol team, the mechanism we have proposed has been implemented in the codebase whereby calldata is mutated off-chain by appending the relevant signature and block expiration argument with the on-chain code extracting these values by using offsets from the end of the call's msg.data.

We consider the present implementation secure as it prevents injection of arbitrary data in between the function's actual payload and the signature validated due to the argsWithSelector variable being assigned to the remainder of msg.data that is not used as part of the signature verification process.

As such, we consider this exhibit fully alleviated.