"Trong smart contract, không có gọi là 'an toàn', chỉ có 'chưa bị khai thác'."

Tuần trước, tôi ngồi đọc lại code của một giao thức lending hàng đầu. Một hàm liquidate() với modifier onlyOwner còn sót lại từ bản fork năm 2020. Dòng code ấy không gây ra lỗi 'reentrancy' kinh điển. Nó tệ hơn. Nó tạo ra một backdoor im lìm, chờ admin key bị lộ. Thị trường đang tăng, TVL đổ về như nước, và mọi người chỉ nhìn vào APY. Họ quên mất rằng, khi lãi suất leo thang, gánh nặng thanh khoản không chỉ đè lên vai người vay, mà còn lên cả architecture của chính giao thức.

Hãy nhìn vào bối cảnh hiện tại. Lãi suất cho vay USDC trên Aave V3 đã chạm ngưỡng 6-7%, mức cao nhất trong 2 năm. Điều này tạo ra một cú hích kép. Một mặt, người gửi tiền (supplier) mừng rỡ vì APY cao. Mặt khác, người vay (borrower) đang phải gồng mình trả lãi. Tỷ lệ thanh lý (liquidation threshold) đang ở mức rất căng. Trên thị trường truyền thống, các ngân hàng trung ương tăng lãi suất để hạ nhiệt nền kinh tế, và các ngân hàng thương mại có bộ đệm vốn để xử lý nợ xấu. Trong DeFi, không có bộ đệm đó. Mọi thứ diễn ra tức thời qua smart contract.
Cơ chế 'thanh lý' (liquidation) vốn được thiết kế để bảo vệ giao thức khỏi nợ xấu. Nhưng nó lại tạo ra một attack vector cực kỳ nguy hiểm khi thị trường biến động mạnh. Tôi đã từng chứng kiến một bot thanh lý tranh nhau mua tài sản thế chấp với giá chiết khấu 5% trong một block duy nhất. Kết quả? Người vay mất sạch tài sản, còn giao thức thì không thu hồi được nợ xấu vì thanh khoản của pool bị khai thác cạn kiệt. Đây là lỗi insufficient liquidity tại lớp giao thức, nhưng triệu chứng thì phát ra từ hành vi thị trường.
Điểm mù bảo mật lớn nhất mà tôi thấy trong các audit gần đây không nằm ở hàm withdraw() hay borrow(). Nó nằm ở cách các giao thức fork code mà không hiểu rõ implied interest rate model của mình. Compound và Aave có những mô hình lãi suất khác nhau. Một bên sử dụng hàm lãi kép tuyến tính, bên kia là hàm lũy thừa. Khi fork, team thường copy y nguyên tham số kink và multiplier. Nhưng điều họ không tính đến là tính thanh khoản của tài sản gốc. Một đồng memecoin có độ biến động 200% không thể có cùng tham số lãi suất như ETH. Kết quả là khi thị trường nóng, lãi suất tăng vọt vượt quá dự kiến, gây ra hiệu ứng 'liquidation cascade'.
Góc nhìn phản trực giác ở đây là: độ phức tạp đang tự sát. Uniswap V4 giới thiệu Hooks, cho phép lập trình viên can thiệp vào mọi khía cạnh của pool. Điều đó rất mạnh mẽ. Nhưng nó biến mỗi DEX thành một Lego kỹ thuật khổng lồ mà chỉ 10% developer thực sự hiểu. Tôi đã thấy một dự án fork hook của Uniswap V4 để thêm cơ chế 'dynamic fee', và vô tình tạo ra lỗ hổng reentrancy tại callback afterSwap(). Lỗi này không có trong code gốc, nhưng được tạo ra bởi 'sự sáng tạo' của team. Fork xong không biết mình đang fork cái chết nào.
Hãy nhìn vào lịch sử. Năm 2021, tôi phát hiện lỗ hổng reentrancy trong batchTransfer của một NFT marketplace. Kẻ tấn công có thể gọi lại hàm trước khi số dư được cập nhật, rút hết token trong pool thanh khoản. Tôi mất 4 giờ để viết PoC. Đội ngũ mất 24 giờ để vá. Nếu kẻ xấu phát hiện trước, thiệt hại ước tính 5 triệu USD. Điều đó cho thấy: kiểm toán không phải là vé an toàn. Nó chỉ là snapshot của một điểm thời gian. Thị trường thay đổi, hành vi người dùng thay đổi, và lỗ hổng mới xuất hiện.

Vậy câu hỏi đặt ra cho các builder: Bạn có đang chạy theo APY để thu hút TVL, hay bạn đang xây dựng một hệ thống có thể chịu được một cuộc tấn công thanh lý quy mô lớn? Nếu lãi suất cho vay tăng lên 15%, pool thanh khoản của bạn có đủ để xử lý 50% vị thế bị thanh lý cùng lúc không? Đa số câu trả lời là không.
Dự báo lỗ hổng của tôi: Trong 6 tháng tới, khi thị trường tăng tiếp tục và lãi suất cho vay đạt đỉnh, chúng ta sẽ chứng kiến ít nhất một vụ 'exploit' lớn từ một giao thức lending đang hot, không phải do lỗi reentrancy kinh điển, mà do sai lầm trong mô hình định giá (pricing model) và thanh khoản (liquidity). Kẻ tấn công sẽ không cần hack code. Họ chỉ cần 'chơi đúng luật' của protocol, khai thác điểm yếu trong oracle và thanh khoản để rút tiền. Còn nhà đầu tư, họ sẽ lại hỏi: Tại sao audit không phát hiện ra? Câu trả lời: Vì audit không test được hành vi thị trường.