Nhật ký phát triển hợp đồng thông minh Rust (7) An toàn hợp đồng và kiểm soát quyền
Bài viết này sẽ giới thiệu về các nội dung liên quan đến kiểm soát quyền trong hợp đồng thông minh Rust từ hai góc độ:
Độ khả dụng của phương thức (hàm) hợp đồng truy cập/gọi
Kiểm soát truy cập chức năng đặc quyền/Phân chia quyền và trách nhiệm
1. Sự khả thi của hàm (phương thức) hợp đồng
Trong việc viết hợp đồng thông minh, việc chỉ định khả năng truy cập của các hàm hợp đồng có thể kiểm soát quyền gọi hàm, từ đó bảo vệ các phần quan trọng trong hợp đồng khỏi bị truy cập hoặc thao tác một cách ngẫu nhiên.
Lấy sàn giao dịch Bancor Network làm ví dụ, sàn giao dịch này đã xảy ra một sự cố an toàn tài sản vào ngày 18 tháng 6 năm 2020 do lỗi trong việc thiết lập quyền truy cập chức năng quan trọng của hợp đồng. Hợp đồng này được viết bằng ngôn ngữ Solidity, và tính khả dụng của các hàm trong hợp đồng được phân thành hai loại: public/external và private/internal. Loại trước cho phép các hàm trong hợp đồng được gọi bởi các bên bên ngoài, có thể coi như một phần của giao diện hợp đồng.
Mạng Bancor đã vô tình đặt một số chức năng chuyển khoản quan trọng trong hợp đồng thành thuộc tính public khi sửa đổi một lỗ hổng bảo mật, dẫn đến việc bất kỳ ai cũng có thể gọi những chức năng này từ bên ngoài hợp đồng để thực hiện các thao tác chuyển khoản. Lỗ hổng quan trọng này đã khiến tài sản trị giá 590.000 đô la của người dùng gặp rủi ro nghiêm trọng.
Trong hợp đồng thông minh Rust, cũng cần chú ý đến việc kiểm soát độ khả kiến của các hàm hợp đồng. Macro #[near_bindgen] được định nghĩa trong NEAR SDK có thể được sử dụng để sửa đổi các hàm hợp đồng thông minh Rust, có các thuộc tính khả kiến khác nhau như sau:
pub fn: biểu thị phương thức này là public, thuộc một phần của giao diện hợp đồng, có thể được gọi từ bên ngoài.
fn: Không chỉ định công khai rõ ràng, có nghĩa là không thể gọi trực tiếp từ bên ngoài hợp đồng, chỉ có thể gọi bên trong hợp đồng.
pub(crate) fn: Giới hạn phương thức được gọi trong phạm vi nội bộ của crate.
Một cách khác để thiết lập phương thức hợp đồng thành internal là định nghĩa một khối mã impl Contract độc lập không được sửa đổi bằng #[near_bindgen] trong hợp đồng.
Đối với hàm callback (Callbacks), khi định nghĩa phải được đặt thuộc tính public để có thể gọi qua function call. Đồng thời cần đảm bảo rằng hàm callback không thể bị người khác gọi tùy ý, tức là người gọi phải là hợp đồng tự thân. NEAR SDK cung cấp macro #[private] để thực hiện chức năng này.
Cần lưu ý rằng, trong ngôn ngữ Rust, mặc định tất cả nội dung đều là private, ngoại trừ các mục con trong pub Trait và các biến Enum trong pub Enum mặc định là public.
2. Kiểm soát truy cập của hàm đặc quyền(cơ chế danh sách trắng)
Ngoài khả năng hiển thị hàm, còn cần thiết lập một cơ chế danh sách trắng kiểm soát truy cập hoàn chỉnh từ góc độ ngữ nghĩa hợp đồng. Một số hàm đặc quyền ( như khởi tạo hợp đồng, kích hoạt/tạm dừng, chuyển khoản đồng nhất ) chỉ có thể được gọi bởi chủ sở hữu hợp đồng (owner), những hàm này thường được gọi là hàm "only owner".
Mặc dù các hàm chính này phải được đặt là thuộc tính public để có thể được gọi từ bên ngoài, nhưng có thể định nghĩa các quy tắc kiểm soát truy cập cho chúng, chỉ khi đáp ứng các quy tắc tương ứng mới có thể thực hiện đầy đủ. Ví dụ, có thể thực hiện Trait tùy chỉnh như sau:
Sử dụng trait này có thể thực hiện kiểm soát truy cập đối với các hàm đặc quyền trong hợp đồng, yêu cầu người gọi phải là chủ sở hữu của hợp đồng. Dựa trên nguyên lý này, có thể tùy chỉnh các modifier hoặc trait phức tạp hơn để thiết lập nhiều người dùng hoặc nhiều danh sách trắng, thực hiện kiểm soát truy cập phân nhóm tinh vi.
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.
9 thích
Phần thưởng
9
6
Chia sẻ
Bình luận
0/400
ContractTester
· 7giờ trước
Lại thấy solidity thất bại, Rust là số một thế giới
Xem bản gốcTrả lời0
ApeEscapeArtist
· 8giờ trước
Rust à, bài học xương máu.
Xem bản gốcTrả lời0
AllTalkLongTrader
· 8giờ trước
Quản lý quyền sao lại phức tạp như vậy?
Xem bản gốcTrả lời0
defi_detective
· 8giờ trước
Lỗi này của Bancor thật sự rất tầm thường, tôi không muốn nói nữa.
Xem bản gốcTrả lời0
GasWastingMaximalist
· 8giờ trước
Quyền hạn đã từng bước vào, trực tiếp nứt ra.
Xem bản gốcTrả lời0
CryptoAdventurer
· 8giờ trước
Lại một lần nữa sàn giao dịch gặp sự cố? Quản lý rủi ro mãi mãi là máy thu thuế trí tuệ đùa với mọi người ah~
An toàn hợp đồng thông minh Rust: Giải thích chi tiết về kiểm soát quyền và quản lý truy cập
Nhật ký phát triển hợp đồng thông minh Rust (7) An toàn hợp đồng và kiểm soát quyền
Bài viết này sẽ giới thiệu về các nội dung liên quan đến kiểm soát quyền trong hợp đồng thông minh Rust từ hai góc độ:
1. Sự khả thi của hàm (phương thức) hợp đồng
Trong việc viết hợp đồng thông minh, việc chỉ định khả năng truy cập của các hàm hợp đồng có thể kiểm soát quyền gọi hàm, từ đó bảo vệ các phần quan trọng trong hợp đồng khỏi bị truy cập hoặc thao tác một cách ngẫu nhiên.
Lấy sàn giao dịch Bancor Network làm ví dụ, sàn giao dịch này đã xảy ra một sự cố an toàn tài sản vào ngày 18 tháng 6 năm 2020 do lỗi trong việc thiết lập quyền truy cập chức năng quan trọng của hợp đồng. Hợp đồng này được viết bằng ngôn ngữ Solidity, và tính khả dụng của các hàm trong hợp đồng được phân thành hai loại: public/external và private/internal. Loại trước cho phép các hàm trong hợp đồng được gọi bởi các bên bên ngoài, có thể coi như một phần của giao diện hợp đồng.
Mạng Bancor đã vô tình đặt một số chức năng chuyển khoản quan trọng trong hợp đồng thành thuộc tính public khi sửa đổi một lỗ hổng bảo mật, dẫn đến việc bất kỳ ai cũng có thể gọi những chức năng này từ bên ngoài hợp đồng để thực hiện các thao tác chuyển khoản. Lỗ hổng quan trọng này đã khiến tài sản trị giá 590.000 đô la của người dùng gặp rủi ro nghiêm trọng.
Trong hợp đồng thông minh Rust, cũng cần chú ý đến việc kiểm soát độ khả kiến của các hàm hợp đồng. Macro #[near_bindgen] được định nghĩa trong NEAR SDK có thể được sử dụng để sửa đổi các hàm hợp đồng thông minh Rust, có các thuộc tính khả kiến khác nhau như sau:
Một cách khác để thiết lập phương thức hợp đồng thành internal là định nghĩa một khối mã impl Contract độc lập không được sửa đổi bằng #[near_bindgen] trong hợp đồng.
Đối với hàm callback (Callbacks), khi định nghĩa phải được đặt thuộc tính public để có thể gọi qua function call. Đồng thời cần đảm bảo rằng hàm callback không thể bị người khác gọi tùy ý, tức là người gọi phải là hợp đồng tự thân. NEAR SDK cung cấp macro #[private] để thực hiện chức năng này.
Cần lưu ý rằng, trong ngôn ngữ Rust, mặc định tất cả nội dung đều là private, ngoại trừ các mục con trong pub Trait và các biến Enum trong pub Enum mặc định là public.
2. Kiểm soát truy cập của hàm đặc quyền(cơ chế danh sách trắng)
Ngoài khả năng hiển thị hàm, còn cần thiết lập một cơ chế danh sách trắng kiểm soát truy cập hoàn chỉnh từ góc độ ngữ nghĩa hợp đồng. Một số hàm đặc quyền ( như khởi tạo hợp đồng, kích hoạt/tạm dừng, chuyển khoản đồng nhất ) chỉ có thể được gọi bởi chủ sở hữu hợp đồng (owner), những hàm này thường được gọi là hàm "only owner".
Mặc dù các hàm chính này phải được đặt là thuộc tính public để có thể được gọi từ bên ngoài, nhưng có thể định nghĩa các quy tắc kiểm soát truy cập cho chúng, chỉ khi đáp ứng các quy tắc tương ứng mới có thể thực hiện đầy đủ. Ví dụ, có thể thực hiện Trait tùy chỉnh như sau:
gỉ pub trait Ownable { fn assert_owner(&self) { assert_eq!(env::predecessor_account_id(), self.get_owner()); } AccountId; fn set_owner(&mut self, owner: AccountId); }
Sử dụng trait này có thể thực hiện kiểm soát truy cập đối với các hàm đặc quyền trong hợp đồng, yêu cầu người gọi phải là chủ sở hữu của hợp đồng. Dựa trên nguyên lý này, có thể tùy chỉnh các modifier hoặc trait phức tạp hơn để thiết lập nhiều người dùng hoặc nhiều danh sách trắng, thực hiện kiểm soát truy cập phân nhóm tinh vi.