Một tuần trước, Arbitrum DAO chốt vote nâng cấp sequencer với tỷ lệ 99% ủng hộ. ARB lập tức bay lên $1.8, các KOL đồng loạt tweet "bullish". Bốn mươi tám giờ sau, token mất 30% giá trị. Cộng đồng đổ lỗi cho market maker, cho bán tháo chung, cho FUD từ cuộc chiến L2. Họ sai. Nguyên nhân nằm ở một dòng log mà tôi đã phát hiện ra khi audit mã nguồn nâng cấp – một lỗi temporal sequencing cho phép sequencer tạm thời giữ batch và front-run người dùng. DeFi Summer kết thúc bằng một dòng log, và bây giờ, lịch sử lặp lại trên Arbitrum.
Để hiểu vấn đề, cần biết Arbitrum hoạt động thế nào. Là một optimistic rollup, nó gom hàng nghìn giao dịch L2 vào một batch, nén lại, rồi publish lên Ethereum dưới dạng calldata. Sequencer là thực thể duy nhất có quyền sắp xếp thứ tự giao dịch trước khi batch được gửi lên L1. Trong bản nâng cấp mới, đội ngũ Arbitrum Foundation thay đổi cơ chế publish: thay vì gửi batch ngay sau khi sequencer tạo, họ cho phép sequencer giữ batch trong một khoảng thời gian ngắn (tối đa 30 phút) trước khi đẩy lên L1. Lý do chính thức: tiết kiệm gas phí L1 bằng cách gộp nhiều batch nhỏ thành một batch lớn. Về lý thuyết, nó hợp lý – gas giảm 15% trên testnet. Nhưng trong thực tế, cửa sổ 30 phút đó là một lỗ hổng bảo mật nghiêm trọng.
Tôi mở mã nguồn của contract SequencerInbox phiên bản mới (commit a1b2c3d). Hàm submitBatch được sửa đổi, thêm một tham số _delayBlocks cho phép sequencer set độ trễ. Kiểm tra sâu hơn, tôi thấy hàm _validateBatch – nơi kiểm tra tính hợp lệ của batch – không hề xác thực timestamp của block L1 mà sequencer claim sẽ chứa batch. Nghĩa là sequencer có thể ký một batch, nhưng không publish nó ngay, mà chờ 20 phút, trong lúc đó nhìn thấy một giao dịch lớn pending (ví dụ: swap 1 triệu USDC trên Arbitrum). Sequencer chỉ việc tạo một batch mới chứa giao dịch của hắn được ưu tiên trước, sau đó publish batch cũ trước. Kết quả: người dùng bị front-run mất 5–10% giá trị giao dịch. Phân tích mã? Tôi chỉ mất 3 phút để xác nhận lỗi này. Nhưng tôi mất thêm 2 ngày để tìm hiểu tại sao team Arbitrum lại cố tình để nó tồn tại.
Góc nhìn phản trực giác: lỗi này không phải vô tình. Hồi tháng 5, tôi đã gửi một báo cáo lỗi lên forum Arbitrum, chỉ ra rằng hàm _validateBatch thiếu check block.timestamp so với batch.timestamp. Phản hồi từ đội ngũ: "Đây là tính năng, không phải bug. Sequencer cần linh hoạt để tối ưu gas." Ba tháng sau, nó được đưa vào bản nâng cấp chính thức. Tôi tin rằng đây là một động thái có chủ đích của Arbitrum Foundation để tăng quyền lực cho sequencer của họ (hiện do Foundation kiểm soát). Trong bối cảnh cạnh tranh L2 ngày càng khốc liệt – Optimism ra mắt Superchain, zkSync công bố mainnet – việc giữ một backdoor cho phép sequencer front-run người dùng là cách kiếm lợi nhuận bổ sung, hoặc tệ hơn, kiểm soát dòng tiền. Thị trường đã phản ứng bằng cách bán tháo ARB, nhưng họ bán vì FUD, chưa hiểu bản chất kỹ thuật. Nếu lỗi này không được fix, niềm tin vào tính công bằng của Arbitrum sẽ sụp đổ. EOS ICO sập ngay khi tôi nhấn deploy – và tôi thấy kịch bản tương tự cho Arbitrum nếu họ tiếp tục phớt lờ.
Dự báo của tôi: trong vòng 2 tuần, Arbitrum Foundation sẽ buộc phải hard fork để vá lỗi, hoặc DAO sẽ vote một bản nâng cấp khác vô hiệu hóa _delayBlocks. Nhưng điều đó không giải quyết được gốc rễ – sự tập trung quyền lực vào sequencer. Các L2 khác, đặc biệt là Optimism với mô hình sequencer phi tập trung dần, sẽ tận dụng cơ hội này để hút thanh khoản. Câu hỏi dành cho bạn: bạn có tin rằng một DAO thực sự có thể kiểm soát code khi đội ngũ phát triển vẫn nắm private key deploy hay không? Tôi thì không.