The Starklane bridge between Ethereum (L1) and Starknet (L2) exhibits potential overconstrained L1 <-> L2 interactions. These asymmetries in validation and functionality between the L1 and L2 sides of the bridge could lead to unexpected behavior, potentially resulting in loss of user funds.
Auto-withdraw flag inconsistency:
The L2 deposit_tokens()
function allows users to set use_withdraw_auto
to true.
However, the L1 withdrawTokens()
function rejects requests with this flag set.
Asymmetric bridge enablement:
The bridge can be enabled/disabled independently on L1 and L2.
Due to the asynchronous nature of cross-chain transactions, a deposit might be initiated when the bridge is enabled, but rejected on withdrawal if the bridge is disabled in the meantime.
The same logic can be applied to whitelist addresses, if the address is removed from whitelist there is no mechanisim to retransfer the tokens.
Lack of address validation:
Neither L1 nor L2 sides implement restrictions on owner/recipient addresses.
This could potentially allow transfers to invalid addresses (e.g., address(0)).
Auto-withdraw flag inconsistency:
Users setting use_withdraw_auto
to true on L2 will have their withdrawals fail on L1.
This results in permanent loss of tokens, as they are burned on L2 but never minted on L1.
Asymmetric bridge enablement:
Users may deposit tokens when the bridge is enabled, but be unable to withdraw if the bridge is disabled before their transaction is processed.
This could lead to temporary or permanent loss of access to funds.
Lack of address validation:
Potential for user error leading to loss of funds if tokens are sent to invalid or unintended addresses.
The overall impact is high, as these issues can lead to permanent loss of user funds with no recovery mechanism.
Manual code review
Auto-withdraw flag:
Modify the L2 deposit_tokens()
function to always set use_withdraw_auto = false
.
Alternatively, ensure the L1 side handles this flag consistently with L2.
Bridge enablement:
Remove the "enabled" check from withdrawal functions on both L1 and L2.
If disabling both deposit and withdraw is required, introduce a separate state variable for this purpose.
Or implement a time-delay mechanism for disabling withdrawals to allow pending transactions to complete.
Or encode the 'enabled' state in the deposit request and use it on the withdraw function on the other side of the bridge.
Address validation:
Implement consistent address validation on both L1 and L2 sides.
At minimum, prevent transfers to address(0) or other known invalid addresses.
General recommendations:
Consider adding recovery mechanisms for trapped funds.
Impact: High, token will be stuck in L2 bridge. Likelyhood: Very low, option is available in L2 but has been disabled since March on L1, would be almost a user error.
Impact: Medium, token won’t be withdrawable until the bridge is enabled again. No real token loss. Likelyhood: Low/Medium, bridge would be disabled in case of emergency/upgrade/audit.
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.