Assessment reports>Gasp Node and Monorepo>Critical findings>Type confusion between ,Withdrawal, and ,Cancel, actions
Category: Coding Mistakes

Type confusion between Withdrawal and Cancel actions

Critical Severity
Critical Impact
High Likelihood

Description

After the updater invokes update_l1_from_l2 to update the Merkle tree root for a given range, anyone can call close_withdrawal or close_cancel to finalize processing of a pending request, perfecting the withdrawal or cancellation according to the corresponding entry in the Merkle tree.

Merkle trees store both Withdrawal and Cancel structs, and the leaf hash function is implemented as keccak256(abi.encode(<struct>)); it does not distinguish between Cancel and Withdrawal nodes with a distinct prefix.

The two data types have identical sizes, and their fields overlap as follows:

Cancel structTypeWithdrawal structType
requestIdRequestIdrequestIdRequestId
Range.startuint256recipientaddress
Range.enduint256tokenAddressaddress
hashbytes32amountuint256

It is possible to submit a call to close_cancel using the Withdrawal struct intended to be provided to close_withdrawal. The Merkle inclusion check would pass because the ABI encoding and therefore the leaf hash are the same. The request would be marked as canceled, preventing the withdrawal with the given ID from being finalized.

Impact

An attacker could race the call to close_withdrawal and call close_cancel using the encoding of the Withdrawal struct and the same merkle_root and proof that would be supplied to close_withdrawal. This would lead to a denial of service and loss of funds.

Recommendations

Use a distinct prefix for all different types of Merkle tree leaves.

We strongly recommend to also differentiate leaves from intermediate nodes. While the current implementation does not seem to be exploitable due to the Merkle tree proof verification functions receiving the depth of the tree as input, this is a common source for vulnerabilities in Merkle tree implementations.

Remediation

This issue has been acknowledged by Gasp, and a fix was implemented in commit 47d82117.

The commit introduces separate hashing functions for each leaf type which prepend a unique prefix. This prevents collisions between hashes for different leaf types.

Zellic © 2025Back to top ↑