The withdraw_auto_from_l1
function in the L2 bridge contract lacks a check for ERC1155 tokens, allowing the transfer of unsupported token types. This contrasts with the L1 depositTokens
function, which explicitly rejects ERC1155 tokens.
This check can easily be sidestepped via the sequencer directly on the L2, potentially leading to unexpected behavior and security risks in handling unsupported token types.
Manual review
Implement a check for ERC1155 tokens in the withdraw_auto_from_l1
function.
The L2 withdraw_auto_from_l1
function does not implement any limit on the number of tokens it processes, unlike the L1 depositTokens
function which enforces a maximum payload length of 300.
This discrepancy could lead to potential out-of-gas errors or excessive resource consumption on the L2 side, causing transaction failures since this can be accessed directly via the sequencer.
Manual review
Implement a maximum token limit in the withdraw_auto_from_l1
function:
The withdraw_auto_from_l1
function lacks a mechanism to prevent replay attacks, similar to the depositTokens()
on L1.
Without this protection, malicious actors could replay the same withdrawal request multiple times, leading to unauthorized token minting or transfers. This vulnerability could significantly compromise the integrity of the bridge and the token ecosystem.
Manual review
Implement a nonce system to track processed requests.
The Solidity implementation on Ethereum (L1) distinguishes between ERC721 and ERC1155 tokens when fetching metadata, while the Cairo implementation on StarkNet (L2) assumes all tokens are ERC721, without checking the token type.
Take a look at the Solidity implementation here and the Cairo implementation here.
This discrepancy can lead to incorrect or missing metadata for ERC1155 tokens, affecting their functionality and potentially causing the bridge to fail or behave unexpectedly when handling these tokens. It could result in loss of metadata, incorrect token information on L2, and a degraded user experience.
Manual review
Add logic in the Cairo deposit_tokens
function to detect the token type (ERC721 vs. ERC1155) and handle metadata fetching accordingly.
L1L2CollectionMappingUpdated
is Currently Unused On The L2The L1L2CollectionMappingUpdated
event is defined but not used in the set_l1_l2_collection_mapping
function.
Low, since StarkNet takes events seriously.
Manual review
Attach the event to set_l1_l2_collection_mapping()
.#
receive()
functionThe contract attempts to prevent receiving Ether by implementing a receive()
function that reverts. However, this protection can be bypassed, allowing Ether to be forcibly sent to the contract.
After conversations with teh sponsors they had indicated that this was implemented as a subtle invariant since they never want to have any eth in their contracts and have no functionality to remove them if need be.
Now while the contract implements a receive()
function that reverts to prevent receiving Ether, there are two ways to bypass this protection:
Using selfdestruct()
: A malicious contract can use selfdestruct()
to forcibly send its balance to any address, including this contract.
Block mining rewards: If the contract's address is set as the recipient of block mining rewards, it will receive Ether regardless of the receive()
function.
These methods can force Ether into the contract without triggering the receive()
function, potentially disrupting the contract's intended behavior if it assumes it will never hold Ether.
The impact is low because:
It doesn't directly lead to loss of funds or critical vulnerabilities.
The contract doesn't seem to rely on the assumption of having zero balance for its core functionality.
However, it breaks the subtle invariant of the contract/system assumption that the contract will never hold Ether.
Manual review
Instead of relying solely on preventing Ether reception, implement a way to handle unexpected Ether in the contract:
ON the cairo side we can never process erc 1155 deposits
This function is used to Deposit tokens to be bridged on the L1, this is in stock to already be used however any erc1155 deposits would not be correctly processed due to us not getting it's metadata.
ERC 1155 deposits onto the l1 from the cairo bridge is not supported.
Support these deposits
ERC 1155 token's metadata can never be retireved
This is from the tokensUtil contract and is the helper function that is to help retrieve the metadata from ERC1155, however it currently hardcodes the return value and instead returns ""
.
ERC 1155 token's metadata can never be retireved
Manual review
Uncomment the lines
The current implementation lacks proper offset and array size checks during serialization operations, which could lead to buffer overflows or out-of-bounds access.
Take a look at the serialization functions, such as uint256ArraySerialize
and cairoStringSerialize
. These functions currently do not perform checks to ensure that the offset and array sizes are within the bounds of the provided buffer.
For example, in uint256ArraySerialize
:
There are no checks to ensure that _offset
remains within the bounds of buf
.
This vulnerability could lead to:
Buffer overflows, potentially overwriting unintended memory areas.
Out-of-bounds access, causing runtime errors or unexpected behavior.
Potential security vulnerabilities if an attacker can manipulate input data to exploit these issues.
Implement bounds checking for all offset operations.
Add array size validation to ensure the buffer can accommodate the serialized data.
Use assert
statements for these checks, as suggested in the TODOs.
Example implementation:
The current implementation of Cairo Short Strings assumes ASCII encoding, limiting the range of characters that can be represented and potentially causing issues with non-ASCII text.
Take a look at the cairoStringPack
and cairoStringUnpack
functions. These functions currently treat each character as a single byte, which is not compatible with UTF-8 encoding where characters can occupy 1 to 4 bytes.
Inability to properly handle non-ASCII characters, leading to data loss or corruption when processing strings containing such characters.
Potential security vulnerabilities if an attacker can exploit this limitation to bypass input validation or cause unexpected behavior.
Incompatibility with systems or data sources that use UTF-8 encoding.
Implement UTF-8 support in the Cairo Short String functions.
Update the packing and unpacking logic to handle multi-byte characters correctly.
Adjust the CAIRO_STR_LEN
constant to account for the maximum number of UTF-8 bytes that can fit in a Cairo Short String, rather than the number of characters.
Example conceptual implementation (note that this would require significant changes to the existing code):
This implementation would require corresponding changes to cairoStringUnpack
and other related functions.
Please, do not suppose impacts, think about the real impact of the bug and check the CodeHawks documentation to confirm: https://docs.codehawks.com/hawks-auditors/how-to-determine-a-finding-validity A PoC always helps to understand the real impact possible.
Serialization and deserialization are made directly on bytes, no data are lost during the transfer.
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.