Mình muốn chia sẻ một điều khá quan trọng mà có thể bạn vẫn chưa hiểu rõ lắm - đó là lỗ hổng reentrancy trong smart contract. Nếu bạn đang phát triển dapp hoặc làm việc với blockchain, cái này là must-know.



Vấn đề cơ bản của reentrancy là gì? Nó xảy ra khi một smart contract gọi đến contract khác, và contract đó có thể gọi ngược lại contract gốc trong khi nó vẫn đang chạy. Kẻ tấn công có thể lợi dụng khoảng thời gian này để đánh cắp tiền.

Hãy tưởng tượng ContractA có 10 Ether và ContractB đã gửi 1 Ether vào đó. Khi ContractB gọi hàm rút tiền, ContractA sẽ kiểm tra xem số dư có lớn hơn 0 không, nếu có thì gửi Ether trả lại. Nhưng ở đây là vấn đề - ContractA chỉ cập nhật số dư sau khi gửi tiền. Nên trong lúc gửi tiền, nếu ContractB có hàm fallback, nó có thể gọi lại hàm rút tiền của ContractA. Vì số dư chưa được cập nhật, kiểm tra sẽ lại thành công, và nó lại nhận thêm 1 Ether. Cái vòng lặp này tiếp tục cho đến khi ContractA hết sạch.

Mình sẽ chỉ bạn ba cách để bảo vệ contract khỏi cuộc tấn công reentrancy này.

Cách thứ nhất là sử dụng modifier nonReentrant. Ý tưởng rất đơn giản - bạn khóa contract trong khi hàm đang chạy. Nếu có ai cố gắng gọi lại hàm đó, nó sẽ bị từ chối vì contract đang bị khóa. Bạn phải chạy hết mã rồi mới mở khóa, và lúc đó kiểm tra sẽ thất bại.

Cách thứ hai là dùng mẫu Checks-Effects-Interactions. Thay vì cập nhật số dư sau khi gửi tiền, bạn cập nhật nó ngay sau kiểm tra nhưng trước khi gửi. Bằng cách này, ngay cả khi contract khác gọi ngược lại, số dư đã là 0 rồi, nên kiểm tra sẽ thất bại. Đó là lý do tại sao thứ tự rất quan trọng - kiểm tra trước, rồi cập nhật hiệu ứng, cuối cùng mới tương tác với contract khác.

Cách thứ ba là tạo một GlobalReentrancyGuard riêng biệt, đặc biệt hữu ích khi bạn có nhiều contract tương tác với nhau. Thay vì bảo vệ từng hàm, bạn tạo một hợp đồng guard dùng chung, lưu trữ trạng thái khóa ở một nơi. Khi bất kỳ contract nào cố gắng nhập một hàm được bảo vệ, nó sẽ kiểm tra với guard này. Nếu guard nói contract đang bị khóa, giao dịch sẽ bị từ chối. Cách này rất mạnh mẽ vì nó ngăn chặn reentrancy không chỉ trong một contract mà còn giữa nhiều contract.

Mình khuyên bạn nên áp dụng cả ba kỹ thuật tùy vào tình huống. Với các hàm rút tiền hoặc chuyển tài sản, luôn sử dụng nonReentrant hoặc Checks-Effects-Interactions. Và nếu dự án của bạn có hệ thống contract phức tạp, hãy xem xét GlobalReentrancyGuard như một lớp bảo vệ thêm.

Đây là một trong những lỗ hổng phổ biến nhất gây mất tiền lớn, nên hiểu rõ về reentrancy là cực kỳ quan trọng nếu bạn muốn viết smart contract an toàn.
XCH-1,00%
TRA1,54%
XEM-1,45%
Trang này có thể chứa nội dung của bên thứ ba, được cung cấp chỉ nhằm mục đích thông tin (không phải là tuyên bố/bảo đảm) và không được coi là sự chứng thực cho quan điểm của Gate hoặc là lời khuyên về tài chính hoặc chuyên môn. Xem Tuyên bố từ chối trách nhiệm để biết chi tiết.
  • Phần thưởng
  • Bình luận
  • Đăng lại
  • Retweed
Bình luận
Thêm một bình luận
Thêm một bình luận
Không có bình luận
  • Đã ghim