The Starklane
contract, which inherits from StarklaneMessaging
, implements a bridge for token transfers between Layer 1 and Layer 2. It uses two methods for message consumption: an auto-withdrawal method and a Starknet core contract method. The StarklaneMessaging
contract uses a mapping _autoWithdrawn
to track the status of messages that can be consumed via the auto method.
The issue lies in the withdrawTokens()
function of the Starklane
contract, which calls _consumeMessageStarknet()
from StarklaneMessaging
. The _consumeMessageStarknet()
function does not adequately check for messages that have already been consumed via the auto method. While it verifies if a message is configured for auto-withdrawal, it fails to check if the message has already been processed through the auto method.
This inconsistency in message status checking creates a critical vulnerability where a single message could theoretically be consumed twice, once through each method. The root cause lies in the incomplete validation within the _consumeMessageStarknet()
function, which only checks for WITHDRAW_AUTO_NONE
status but not for WITHDRAW_AUTO_CONSUMED
.
The issue allows for double consumption of messages, directly enabling double-spending of tokens. Malicious actors can exploit this to withdraw tokens multiple times for a single valid message, resulting in unauthorized token acquisition.
An attacker identifies a valid message for token withdrawal.
The attacker calls a function that uses _consumeMessageAutoWithdraw()
to process the message:
The message is now marked as WITHDRAW_AUTO_CONSUMED
in the _autoWithdrawn
mapping.
The attacker then calls withdrawTokens()
, which internally calls _consumeMessageStarknet()
:
_consumeMessageStarknet()
successfully consumes the message again through the Starknet core contract, as it doesn't check for the WITHDRAW_AUTO_CONSUMED
status.
The attacker potentially withdraws tokens twice for the same message.
Manual review
To address this issue, implement an additional check in the _consumeMessageStarknet()
function to ensure that the message has not already been consumed via the auto method:
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.