1. Hợp đồng Nhà máy Sputnik-DAOSputnik-DAO áp dụng mẫu thiết kế nhà máy sáng tạo (Factory Pattern) để thực hiện việc tạo và quản lý thống nhất tổ chức tự trị phi tập trung (DAO) của nền tảng.
Bài viết này sẽ giới thiệu chi tiết về thiết kế và triển khai mô hình nhà máy nền tảng Sputnik-DAO (sputnikdao-factory).
Kho mã nguồn của hợp đồng tương ứng được đặt tại: https://github.com/near-daos/sputnik-dao-contract/tree/518ad1d97614fff4b945aba75b6c8bd2483187a2

tiêu đề cấp đầu tiên
2. Giới thiệu chức năng mô-đun DAPP
Mở trang DAPP của nền tảng Sputnik DAO, có thể thấy rằng nhiều tổ chức tự trị phi tập trung đã tạo và tùy chỉnh các đối tượng dụ DAO của riêng họ (hợp đồng Sputnikdaov2) trên nền tảng.
Kể từ tháng 3 năm 2022, DAO hoạt động tích cực nhất được tạo dưới nền tảng này là news.sputnik-dao.near, trong đó 3051 đề xuất (đề xuất) đang được bỏ phiếu công khai hoặc trạng thái đã bị đóng.

📄Để thuận tiện cho độc giả, sơ đồ cấu trúc của hợp đồng được cung cấp ở trên để tham khảo.

Nghĩa là, tất cả các hợp đồng phiên bản DAO được tạo dựa trên nền tảng Sputnik DAO đều được triển khai trong các tài khoản phụ của tài khoản NEAR, ví dụ:
pcp.sputnik-dao.near
test-dao-bro.sputnik-dao.near
blaqkstereo.sputnik-dao.near
octopode-dao.sputnik-dao.near
Để biết định nghĩa về tài khoản phụ trong Giao thức NEAR, bạn có thể tham khảo tại https://docs.near.org/docs/concepts/account#subaccounts 🔗.
Như thể hiện trong hình bên dưới, các tổ chức phi tập trung có thể bắt đầu giao dịch một cách công khai trên mạng chính NEAR và tạo các phiên bản DAO mới bằng cách gọi phương thức create() được cung cấp bởi hợp đồng sputnikdao-factory.

3. Giải thích mã hợp đồng sputnikdao-nhà máy
Để giúp các bạn hiểu rõ hơn về cách viết hợp đồng Rust factory mode, bài viết này sẽ đi sâu giải thích mã hợp đồng của sputnikdao-factory.
3.1 Tạo DAO
Tình trạng hợp đồng sputnikdao-nhà máy chủ yếu bao gồm hai phần sau:

factory_manager: Việc triển khai logic chức năng nội bộ chính của hợp đồng, cung cấp một loạt các phương thức để tạo/xóa/cập nhật các phiên bản DAO.
dao: thông qua cấu trúc dữ liệu bộ sưu tập, ghi lại địa chỉ tài khoản GẦN của tất cả các phiên bản DAO đã tạo trong lịch sử của nền tảng.
Phương thức hợp đồng sputnikdao-factory create() được sử dụng để tạo các phiên bản DAO được định nghĩa như sau:

Chức năng của các dòng 3-5 của mã là hoàn thành tên người dùng được chỉ định bởi tham số chức năng khi gọi phương thức create(), để có được địa chỉ tài khoản phụ NEAR để triển khai hợp đồng DAO trong tương lai. Ở đây env::current_account_id() đề cập đến địa chỉ của hợp đồng sputnikdao-factory, cụ thể là sputnik-dao.near.
Các dòng 6-11 của mã xây dựng tham số hàm của hàm gọi lại on_create sau khi phương thức create() gọi factory_manager.create_contract.
Dòng 12-19 của mã gọi giao diện create_contract được cung cấp bởi factory_manager trong hợp đồng nhà máy để tạo và triển khai hợp đồng phiên bản DAO mới cho người gọi phương thức create(). Đồng thời, đối với hợp đồng phiên bản DAO mới được triển khai, thông tin cấu hình cơ bản của hợp đồng có thể được chuyển dưới dạng chuỗi Base64 thông qua tham số create_contract args.
Sau đây là giao dịch được sử dụng bởi một tổ chức phi tập trung trong mạng chính NEAR để tạo hợp đồng phiên bản DAO trên nền tảng Sputnik-DAO:
FyECaggFxATGaUMrRKkbotRWAPkhjw5SBnZfRHpzSiQ8🔗
Giao dịch này gọi phương thức create() trong mã hợp đồng sputnikdao-factory, thực hiện việc tạo tài khoản phụ multicall.sputnik-dao.near và triển khai thành công mã hợp đồng của phiên bản DAO tương ứng (chi tiết triển khai cụ thể sẽ được chi tiết sau này mở rộng mô tả).


Nội dung cụ thể của tham số args sau khi giải mã Base64 là:
Nội dung này chính xác là thông tin cấu hình hợp đồng được yêu cầu khi thực hiện phương thức khởi tạo hợp đồng new() khi triển khai hợp đồng multicall.sputnik-dao.near.
Bài viết dưới đây sẽ phân tích cụ thể việc triển khai factory_manager.create_contract:

Các tham số của chức năng này được quy định như sau:
code_hash: Giá trị băm của mã mẫu hợp đồng phiên bản DAO tiêu chuẩn do nền tảng Sputnik-DAO cung cấp.
account_id: Tài khoản triển khai của hợp đồng phiên bản DAO mới được tạo trong tương lai, chẳng hạn như multicall.sputnik-dao.near, nội dung của tham số này đã được xây dựng trong hàm trên create() của create_contract().
new_method: Chỉ định chức năng khởi tạo hợp đồng trong hợp đồng cá thể DAO mới được tạo, thường là new().
args: Thông tin cấu hình cần thiết để thực thi chức năng khởi tạo hợp đồng phiên bản DAO mới(), bao gồm hai khía cạnh sau:
Thông tin cơ bản về DAO được cung cấp bởi tổ chức tự trị phi tập trung: Config

5. callback_method: Chỉ định chức năng gọi lại sau khi phương thức create_contract() được thực thi, được sử dụng để duy trì và xử lý thông tin của hợp đồng phiên bản DAO mới trong hợp đồng xuất xưởng này.
6. callback_args: Tham số chức năng của hàm gọi lại.
Việc thực hiện chức năng này chủ yếu được chia thành các bước sau:
Các dòng 15-22 của mã tìm và tải mã mẫu hợp đồng phiên bản DAO (định dạng wasm) do hợp đồng nhà máy cung cấp vào thanh ghi được đánh số 0 theo code_hash.
Các dòng 23-25 của mã xây dựng một Lời hứa để theo dõi kết quả xử lý của tất cả các bước sau (3-6).
Dòng 26-27 của mã tạo tài khoản để triển khai hợp đồng phiên bản DAO.
Mã 28-29 chuyển mã thông báo NEAR sang tài khoản mới tạo, bắt nguồn từ số tiền attachment_deposited bởi người gọi phương thức tạo () hợp đồng ban đầu của nhà máy.
Các dòng 30-31 của mã đọc mã wasm từ thanh ghi 0 và triển khai hợp đồng.
Các dòng 32-41 của mã gọi hàm khởi tạo new() của mã hợp đồng phiên bản DAO.
Sau khi hợp đồng phiên bản DAO cuối cùng được triển khai, hàm on_create() sẽ được gọi lại ở cuối mã thực thi factory_manager.create_contract() dài 32-53 dòng.
Sau đây là cách triển khai mã nội bộ của hàm gọi lại on_create:
Logic xử lý cụ thể của chức năng này là:
Nếu có lỗi ở các bước trên (3-6) và không thể thực thi bình thường, kết quả trả về của Promise thu được bằng cách gọi truy vấn near_sdk::is_promise_success() trong hàm gọi lại on_create() sẽ là false. Tại thời điểm này, số lượng mã thông báo NEAR được đính kèm bởi người gọi phương thức tạo () hợp đồng ban đầu của nhà máy sẽ được hoàn trả.
Nếu các bước trên (3-6) được thực hiện chính xác, điều đó có nghĩa là hợp đồng phiên bản DAO mới (Sputnikdaov2) do người dùng yêu cầu đã được tạo bình thường. Đồng thời, hợp đồng nhà máy sẽ ghi lại và theo dõi địa chỉ tài khoản phụ của hợp đồng phiên bản DAO.
tiêu đề phụ

chữ
chữ
chữ
Mã được đặt tại: sputnikdao-factory2/src/lib.rs # Line136-149
Chi tiết xử lý của factory_manager.update_contract() như sau: Giao diện này có thể thực hiện lệnh gọi của hàm update() trong hợp đồng phiên bản DAO tương ứng.
Điều đáng nói là:
Trong quá trình phân tích mã Sputnik-DAO, BlockSec đã tìm thấy một vấn đề bảo mật nghiêm trọng trong hợp đồng Nhà máy của mình, điều này sẽ ảnh hưởng đến tất cả các hợp đồng sử dụng Sputnik-DAO. Sau khi liên hệ với bên dự án, Vấn đề cuối cùng đã được xác nhận và khắc phục kịp thời.
💡Lỗ hổng bảo mật được mô tả cụ thể như sau:
Trong phiên bản trước của mã, phương thức cập nhật công khai() được cung cấp bởi hợp đồng nhà máy sputinikdao thiếu kiểm tra xác nhận khóa sau. Điều này dẫn đến việc bất kỳ ai cũng có thể gọi phương thức này.
Thật trùng hợp, hợp đồng phiên bản DAO (hợp đồng Sputnikdaov2) cho phép Nhà máy Sputnik-DAO nâng cấp hợp đồng này thông qua các cuộc gọi hợp đồng chéo theo mặc định.
Phương thức update() được triển khai trong hợp đồng phiên bản DAO như sau, mã nằm trong sputnikdao2/src/upgrade.rs # Dòng 62
Trong dòng 9 của đoạn mã trên, giá trị của factory_info.auto_update được đặt thành True theo mặc định khi hợp đồng phiên bản DAO triển khai và gọi phương thức new() để khởi tạo.
Phương thức new() của hợp đồng phiên bản DAO được triển khai như sau: mã nằm trong sputnikdao2/src/lib.rs # Dòng 83-104
Tóm lại, một người dùng thông thường (không phải hợp đồng Factory và chính hợp đồng DAO) có thể nâng cấp (giả mạo) mã của bất kỳ hợp đồng DAO nào thông qua phương thức pub fn update() do hợp đồng Factory cung cấp, sẽ cung cấp cho nền tảng Sputnik-DAO và Tất cả các dự án hợp đồng dựa trên nền tảng Sputnik-DAO đều mang lại rủi ro bảo mật lớn.
🪴 May mắn thay, khi sự cố này được phát hiện, mã của phiên bản này vẫn chưa được tung ra trên NEAR mainnet nên không có tổn thất nào.
Do phản ứng nhanh chóng của bên dự án, lỗ hổng đã được khắc phục chính xác bằng cách thêm cơ chế xác minh danh sách trắng hợp lý😊
tiêu đề cấp đầu tiên
chữ
Ngoài các lỗ hổng được phát hiện và khắc phục ở trên, tính bảo mật của hợp đồng Nhà máy Sputnik-DAO chủ yếu được đảm bảo từ các khía cạnh sau:
[Kiểm soát truy cập] Phương thức xem của hợp đồng không được sửa đổi các biến trạng thái của hợp đồng, nghĩa là tham số đầu tiên trong định nghĩa phương thức phải được đặt thành &self, không phải &mut self.
Không có chức năng nào sau đây sửa đổi các biến trạng thái:
get_owner(&self)
get_number_daos(&self)
get_default_version(&self)
get_default_code_hash(&self)
get_daos(&self, from_index: u64, limit: u64)
get_dao_list(&self)
get_contracts_metadata(&self)
get_code(&self, code_hash: Base58CryptoHash)
[Kiểm soát truy cập] Các chức năng đặc quyền được mở bởi hợp đồng, các chức năng này chỉ có thể được thực thi bởi chủ sở hữu hợp đồng (hoặc tài khoản hợp đồng DAO) và có các xác nhận tương ứng trong phương thức, ví dụ:

Do phản ứng nhanh chóng của bên dự án, lỗ hổng đã được khắc phục chính xác bằng cách thêm cơ chế xác minh danh sách trắng hợp lý😊
Xem Cam kết sửa lỗi này: 518ad1d97614fff4b945aba75b6c8bd2483187a2🔗