# Nonce ordering of EOA can be updated to "arbitrary" through an L1 tx

Default EOA can call ContractDeployer.updateNonceOrdering via an L1 priority tx, flipping nonce ordering to arbitrary and permanently freezing the account.

- Payout: Contest reward
- Severity: medium
- Program: zkSync
- Credited: xuwinnie
- Disclosed: 2024-02-29
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2023-10-zksync-findings/issues/861
- Library page: https://bugbountylibrary.com/r/c4%3A2023-10-zksync%3AM-06
- Tags: domain:web3 impact:dos kind:contest platform:code4rena sev:medium technique:chained technique:source-review vuln:access-control vuln:business-logic

**Target:** ContractDeployer / NonceHolder system contracts on zkSync Era
**Root cause:** The L2 bootloader only sets isSystemCall for create/create2/createAccount selectors, but the L1 msgValueSimulatorMimicCall sets isSystem=true for any call to ContractDeployer, so updateNonceOrdering (onlySystemCall) is reachable from an L1 priority tx.
**Steps:**
1. Observe _execute sets isSystemCall only for create/create2/createAccount/create2Account selectors on ContractDeployer.
2. Observe L1 path msgValueSimulatorMimicCall sets isSystem = (to == CONTRACT_DEPLOYER_ADDR()) unconditionally.
3. Submit an L1 priority transaction targeting ContractDeployer with calldata `updateNonceOrdering(Arbitrary)` from an EOA.
4. updateNonceOrdering passes onlySystemCall, flips accountInfo.nonceOrdering to Arbitrary permanently.
5. Subsequent L2 txs fail: incrementMinNonceIfEquals requires sequential nonce while isNonceUsed honors arbitrary ordering, so account is frozen.
**How found:** Code-reading of the two call paths: compared the L2 bootloader's selector whitelist for isSystemCall against the L1 msgValueSimulatorMimicCall which sets isSystem purely by target address, spotting the inconsistency.
**Exploitation:** Attacker (or the account owner) sends an L1 priority tx to ContractDeployer calling updateNonceOrdering(Arbitrary); the L1 path marks it as a system call, the change is permanent, and the EOA can no longer initiate transactions.
**Insight:** When two entry paths (L1 priority vs L2 bootloader) compute the same 'system call' privilege flag differently, diff the two implementations; a target-address-only check on one path lets any system-contract-only function be invoked by a normal EOA.
