Resources

People often ask me "How did you learn how to hack?" The answer: by reading. This page is a collection of the blog posts and other articles that I have accumulated over the years of my journey. Enjoy!

DoubleUp Roll: Double-spending in Arbitrum by Rolling It Back- 1618

Hong Kong PolytechnicPosted 1 Year Ago
  • Arbitrum and Optimism are Optimistic Rollups. This means that they are an L2 blockchain that inherits the security of the L1 by posting all of the L2 data to the L1. There are several rolls with these blockchains:
    • Sequencer: Creates the blocks from the submitted transactions to its private mempool.
    • Batcher: Posts the transaction information to the Ethereum L1. This allows to deriving of the state of the L2 from only Ethereum, making it a rollup instead of a sidechain.
    • Publisher: Posts the L2 consensus state to Ethereum. There is also a Challenger that can submit fraud proofs is something is done wrong by the Publisher.
  • The transaction lifecycle of an L2 is as follows:
    1. User submits transaction to RPC on L2 or to specific contract on L1.
    2. Sequencer creates a block and broadcasts it to the L2. The block is soft finalized.
    3. The block information is posted to Ethereum via the Batcher role for the Data Availability part of a rollup.
    4. The posted batch is seen by the L2 nodes. This makes the block hard-finalized.
    5. If the batch is different than the current state of the L2 then a rollback is done on the soft-finalized transactions.
  • There are three scenarios where rollbacks can occur that are relevant:
    • If the block time gap is too different on the L1 compared to the L2, then the block will be rolled back. This is a security mechanism to prevent too much manipulation of the block.timestamp in Solidity.
    • In case of the Sequencer going down, transactions can be forced through the L1, after a 24 hour delay. If the transaction was never included in the L1 but was in an L2 block then this forced inclusion will trigger a rollback.
    • Invalid posted batch information to the L2 not being processed on the L1. This leads to a rollback on the L2.
  • The goal of this paper is to force trigger rollbacks to have a double spend via deposits/withdrawls or after a large amount of blocks have passed to break bridges. Using the rollback mechanisms above, this is what they do. Of course, this requires some Tomfoolery to get transactions delayed properly.
  • In the Overtime attack, the goal is to change the time on a deposit that has already been used. It works as follows:
    1. Cause a major delay in the batch processing. This is no "one" way to do this.
    2. Submit deposit to the L2.
    3. L2 accepts the deposit.
    4. Batcher is unable to submit the the deposit to the L1 because of batching delays done in step 1.
    5. Attacker initiates and gets a withdrawal accepted for their recent deposit.
    6. Time-bound mechanism springs into action! The L2 block has its block rolled back.
    7. L1 deposit is processed in the new L2 block. Now, we have two sets of funds from the same deposit. Personally, I'm confused on how the withdrawal gets processed before the redoing of the finalization on the L1.
  • In the QueueCut Attack, the liveness preservation is abused.
    1. Introduce a delay in the L2 to L1 comms by adding a bunch of transactions with incompressable data.
    2. Trigger deposit from the L1. This will soft finalization immediately.
    3. Trigger a withdrawal on the L2 with that deposit. This will be processed quickly.
    4. Because of the delay and queue, the force inclusion feature can now be used. Use this to trigger a deposit.
    5. Force inclusion negates the L2 block that had the original deposit. Hence, we have a double spend.
  • The ZipBomb attack is making data uncompressable from the perspective of the Sequencer. This leads to the L1 refuses to process the L2 block, leading to a rollback. To me, the asynchronous processing is weird. I thought that the blocks would build on each other and require a perfect order. In reality, this isn't the case, which allows for the weird ordering of things. I imagine that many of these ideas came from noticing a bad state machine vs. the rollback mechanics being able to be DoSed.
  • The fixes to these bugs are not just a couple lines of code - they are design-level fixes because of the asynchronous processing. Both Optimism and Arbitrum having a streaming mechanism to ensure that blocks can always be handled. To mitigate the Zip Bomb attack, Arbitrum now only cares about the plaintext size on submission and not the compressed size.
  • On Optimism, they added a fee prioritization structure instead of a first-come-first-server queue. Additionally, instead of the more complicated one-block-per-transaction strategy, they now use a 2-second fixed interval. As far as cross-chain bridges go, there are still some concerns. They urged products to wait until L1 inclusion instead of L2 block confirmations.