sách gpt4 ai đã đi

Làm thế nào để xây dựng DAO (Tổ chức tự trị phi tập trung) trong Solidity?

In lại Tác giả: Tôi là một chú chim nhỏ Thời gian cập nhật: 2023-04-05 22:34:11 26 4
mua khóa gpt4 Nike

Bài viết này sẽ giúp bạn hiểu khái niệm DAO và xây dựng một DAO cơ bản.

DAO là gì?

Bạn có thể coi DAO là một thực thể hoạt động trên Internet (giống như một doanh nghiệp) do các cổ đông (những thành viên sở hữu mã thông báo và quyền biểu quyết theo tỷ lệ) cùng sở hữu và quản lý. Trong DAO, các quyết định được đưa ra thông qua các đề xuất mà các thành viên của DAO có thể bỏ phiếu và sau đó thực hiện.

DAO được quản lý hoàn toàn bằng mã có thể xem/xác minh công khai, không có cá nhân nào (như CEO) chịu trách nhiệm ra quyết định.

DAO hoạt động như thế nào?

Như đã đề cập trước đó, DAO được quản lý bằng mã, nhưng điều gì sẽ xảy ra nếu người điều hành máy chạy mã quyết định tắt máy hoặc chỉnh sửa mã?

Điều cần thiết là phải có cùng một mã chạy trên một nhóm máy do nhiều thực thể khác nhau lưu trữ, để ngay cả khi một máy bị hỏng, máy khác vẫn có thể tiếp quản. Blockchain giúp chúng ta giải quyết các vấn đề trên. Blockchain dựa trên EVM (như Ethereum và Polygon) cho phép chúng ta chạy các hợp đồng thông minh trên sổ cái phi tập trung công khai. Các hợp đồng thông minh được triển khai trên các mạng này sẽ được truyền đến tất cả các nút trên mạng nơi chúng có thể xem và xác minh, và không có bên nào kiểm soát mạng.

DAO với tư cách thành viên được mã hóa sẽ phát hành mã thông báo cho các thành viên của mình, đại diện cho quyền biểu quyết trong hệ thống. Tùy thuộc vào cơ chế quản trị, bất kỳ ai cũng có thể tạo đề xuất thay đổi DAO và gửi đề xuất đó để bỏ phiếu với số lượng đại biểu tối thiểu (tỷ lệ phần trăm/số phiếu tối thiểu cần thiết để thông qua) và thời gian bỏ phiếu. Các thành viên có thể xem và bỏ phiếu cho các đề xuất, với quyền biểu quyết tỷ lệ thuận với số lượng token họ sở hữu. Sau khi thời gian bỏ phiếu kết thúc, chúng tôi sẽ kiểm tra xem đề xuất có được thông qua hay không và nếu được thì sẽ thực hiện.

Một số ví dụ về DAO là MakerDAO và Aragon.

Sơ đồ sau đây cho thấy quá trình này.

tài liệu

Hãy bắt đầu xây dựng

Chúng tôi sẽ sử dụng hợp đồng OpenZeppelin trong cơ sở mã của mình và tôi cũng sẽ sử dụng một số mã từ mẫu DAO của Patrick Collins.

Điều kiện tiên quyết

Bạn sẽ cần những thứ sau để bắt đầu.

  1. Node.js: Bạn có thể sử dụng Tải phiên bản mới nhất từ ​​trang web. Phiên bản tôi đang sử dụng tại thời điểm viết bài viết này là 16.14.2.
  2. Sợi len : Chúng ta sẽ sử dụng Y arn làm trình quản lý gói.
  3. mũ cứng :Chúng tôi sẽ sử dụng Hardhat làm môi trường phát triển cục bộ.

Cơ sở dữ liệu

Tôi đã viết mã và đẩy nó lên GitHub, bạn có thể tải nó ở đó nếu muốn tự mình thử, nhưng tôi khuyên bạn nên ở lại để tôi giải thích mã.

Kịch bản

Chúng tôi sẽ xây dựng một DAO có thể thực hiện những chức năng sau:

Cảnh 1.

  1. Thêm thành viên ban đầu. (Chúng ta hãy gọi họ là những người sáng lập).
  2. Yêu cầu những người sáng lập đưa ra đề xuất. (Đề xuất một chức năng sẽ được thực hiện trên hợp đồng thông minh).
  3. Hãy để Người sáng lập bỏ phiếu cho đề xuất trên và vì Người sáng lập nắm giữ 100% quyền biểu quyết nên đề xuất sẽ được thông qua.
  4. Thực hiện đề xuất. (và chức năng trong hợp đồng thông minh)

Cảnh 2.

  1. Thêm một thành viên ban đầu (chúng ta sẽ gọi họ là Người sáng lập).
  2. Thêm một thành viên khác và cấp cho họ mã thông báo mới có giá trị bằng 20% ​​cổ phần của người sáng lập.
  3. Yêu cầu người sáng lập tạo ra đề xuất (đề xuất một chức năng sẽ được thực hiện trên hợp đồng thông minh).
  4. Yêu cầu người sáng lập và thành viên mới bỏ phiếu cho đề xuất trên. Số lượng người tham dự được ấn định là 90%.
  5. Thực hiện các đề xuất (và chức năng trong hợp đồng thông minh).

hợp đồng

Như đã đề cập trước đó, chúng tôi sẽ sử dụng hợp đồng quản trị của OpenZeppelin. Hợp đồng như sau:

  1. Hợp đồng của Thống đốc: Hợp đồng của Thống đốc xác định số phiếu bầu/tỷ lệ phần trăm cần thiết để đủ điều kiện (ví dụ: nếu đủ điều kiện là 4%, thì chỉ cần 4% cử tri bỏ phiếu để thông qua đề xuất), thời gian bỏ phiếu tức là thời gian mở phiếu bầu và thời gian trì hoãn bỏ phiếu tức là thời gian sau khi đề xuất được tạo, các thành viên được phép thay đổi số lượng mã thông báo mà họ sở hữu. Thống đốc cũng có quyền đưa ra đề xuất, bỏ phiếu và thực hiện đề xuất.
  2. Khóa thời gian: Hợp đồng TimeLock cung cấp thời gian cho các thành viên không đồng ý với quyết định thoát khỏi hệ thống trước khi quyết định được thực hiện.
  3. Mã thông báo: Hợp đồng Token là một loại hợp đồng ERC20 đặc biệt triển khai tiện ích mở rộng ERC20Votes. Điều này cho phép quyền biểu quyết được ánh xạ vào ảnh chụp nhanh số dư trong quá khứ thay vì số dư hiện tại, giúp ngăn chặn các thành viên biết rằng một đề xuất quan trọng sắp được đưa ra và cố gắng tăng quyền biểu quyết của họ bằng cách mua thêm mã thông báo rồi bán chúng sau khi bỏ phiếu.
  4. Mục tiêu: Đây là hợp đồng có mã lệnh sẽ được thực thi sau khi đề xuất được thông qua bỏ phiếu.

Mã số

Chúng ta hãy bắt đầu tổng hợp tất cả lại nhé. Tạo một dự án mẫu trống bằng Hardhat. Chạy lệnh sau trong terminal của bạn.

thêm sợi — Phát triển mũ bảo hiểm.

Tiếp theo, chúng ta hãy tạo cấu trúc thư mục bằng hardhat.

Bạn sẽ thấy lời nhắc như thế này.

tài liệu

Nhấp vào Tạo dự án mẫu cơ bản. Khi quá trình hoàn tất, bạn sẽ thấy nội dung tương tự như thế này.

tài liệu

hợp đồng

Chúng ta hãy bắt đầu thêm hợp đồng, trước tiên hãy thêm GovernorContract. Chúng ta có thể lấy mã tương tự từ OpenZeppelin hoặc bạn có thể sao chép mã bên dưới hoặc sao chép mã từ kho lưu trữ của tôi. Mã hợp đồng của tôi khắc phục sự cố trong phiên bản OpenZeppelin, cũng như tham số hóa độ trễ bỏ phiếu, số lượng đại biểu đủ để biểu quyết và thời gian bỏ phiếu tương tự như phiên bản của Patrick Collins.

                        
                          // SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import “@openzeppelin/contracts/governance/Governor.sol”; import “@openzeppelin/contracts/governance/extensions/GovernorSettings.sol”; import “@openzeppelin/contracts/governance/extensions/GovernorCountingSimple.sol”; //import “@openzeppelin/contracts/governance/extensions/GovernorVotes.sol”; import “@openzeppelin/contracts/governance/extensions/GovernorVotesQuorumFraction.sol”; import “@openzeppelin/contracts/governance/extensions/GovernorTimelockControl.sol”; contract GovernorContract là Governor, GovernorSettings, GovernorCountingSimple, GovernorVotes, GovernorVotesQuorumFraction, GovernorTimelockControl { constructor(IVotes _token, TimelockController _timelock,uint256 _quorumPercentage, uint256 _votingPeriod, uint256 _votingDelay) Governor("GovernorContract") GovernorSettings(_votingDelay,_votingPeriod,0) GovernorVotes(_token) GovernorVotesQuorumFraction(_quorumPercentage) GovernorTimelockControl(_timelock) {} // Các hàm sau là các hàm ghi đè bắt buộc của Solidity. function votingDelay() public view override(IGovernor, GovernorSettings) returns (uint256) { return super.votingDelay(); } function votingPeriod() public view override(IGovernor, GovernorSettings) returns (uint256) { return super.votingPeriod(); } function quorum(uint256 blockNumber) public xem ghi đè (IGovernor, GovernorVotesQuorumFraction) trả về (uint256) { trả về super.quorum(blockNumber); } hàm getVotes (địa chỉ tài khoản, uint256 blockNumber) công khai xem ghi đè (Governor, IGovernor) trả về (uint256) { trả về _getVotes (tài khoản, blockNumber, _defaultParams()); } hàm trạng thái (uint256 proposalId) công khai xem ghi đè (Governor, GovernorTimelockControl) trả về (ProposalState) { trả về super.state (proposalId); } hàm đề xuất (địa chỉ [] mục tiêu bộ nhớ, uint256 [] giá trị bộ nhớ, byte [] dữ liệu cuộc gọi bộ nhớ, mô tả bộ nhớ chuỗi) công khai ghi đè (Governor, IGovernor) trả về (uint256) { trả về super.propose (mục tiêu, giá trị, dữ liệu cuộc gọi, mô tả); } hàm proposalThreshold() công khai xem ghi đè (Governor, GovernorSettings) trả về (uint256) { trả về super.proposalThreshold(); } hàm _execute(uint256 proposalId, address[] memory targets, uint256[] memory values, bytes[] memory calldatas, bytes32 descriptionHash) ghi đè nội bộ(Governor, GovernorTimelockControl) { super._execute(proposalId, targets, values, calldatas, descriptionHash); } hàm _cancel(address[] memory targets, uint256[] memory values, bytes[] memory calldatas, bytes32 descriptionHash) ghi đè nội bộ(Governor, GovernorTimelockControl) trả về (uint256) { trả về super._cancel(targets, values, calldatas, descriptionHash); } hàm _executor() ghi đè chế độ xem nội bộ(Governor, GovernorTimelockControl) trả về (address) { trả về super._executor(); } hàm supportsInterface(bytes4 interfaceId) ghi đè chế độ xem công khai(Governor, GovernorTimelockControl) trả về (bool) { return super.supportsInterface(interfaceId); } }

                        
                      

Tiếp theo, chúng ta hãy thêm hợp đồng mã thông báo, cũng có sẵn trên OpenZeppelin. Mã của tôi có thêm hàm "issueToken" (sẽ nói rõ hơn sau).

                        
                          // SPDX-License-Identifier: MIT pragma solidity ^0.8.2; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol"; contract MyToken là ERC20, ERC20Permit, ERC20Votes { constructor() ERC20("MyToken", "MTK") ERC20Permit("MyToken") { _mint(msg.sender, 1000); } // Các hàm bên dưới là các lệnh ghi đè bắt buộc của Solidity. function _afterTokenTransfer(address from, address to, uint256 amount) internal override(ERC20, ERC20Votes) { super._afterTokenTransfer(từ, đến, số tiền); } hàm _mint(địa chỉ đến, số tiền uint256) ghi đè nội bộ(ERC20, ERC20Votes) { super._mint(đến, số tiền); } hàm _burn(địa chỉ tài khoản, số tiền uint256) ghi đè nội bộ(ERC20, ERC20Votes) { super._burn(tài khoản, số tiền); } hàm issueToken(địa chỉ đến, số tiền uint256) công khai{ _mint(đến, số tiền); } }

                        
                      

Cuối cùng, chúng ta hãy xem xét hợp đồng Target. Trong ví dụ của chúng ta, chúng ta sẽ sử dụng cùng hợp đồng Box mà Patrick Collins đã sử dụng.

                        
                          // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/governance/TimelockController.sol"; contract TimeLock là TimelockController { // minDelay là khoảng thời gian bạn phải đợi trước khi thực thi // proposalrs là danh sách các địa chỉ có thể đề xuất // executors là danh sách các địa chỉ có thể thực thi constructor( uint256 minDelay, address[] memory proposalrs, address[] memory executors ) TimelockController(minDelay, proposalrs, executors) {} }

                        
                      

Bài kiểm tra

Bây giờ chúng ta đã có hợp đồng, chúng ta cần viết bài kiểm tra. Tạo tệp "sample-test.js" trong thư mục "test". Chúng ta hãy bắt đầu viết bài kiểm tra nhé. Đầu tiên, hãy tạo một tệp cấu hình có tên "helper.config.js" với dữ liệu sau.

                        
                          module.exports = { MIN_DELAY:3600, QUORUM_PERCENTAGE:90, PERIOD_VOTING:5, VOTING_DELAY:3, ADDRESS_ZERO :"0x0000000000000000000000000000000000000000000000000" }

                        
                      

Tỷ lệ biểu quyết là 90%, thời gian bỏ phiếu là 5 khối và thời gian trì hoãn bỏ phiếu là 3 khối. Độ trễ tối thiểu cho TimeLock là 3600 giây.

Hãy viết mã để triển khai tất cả các hợp đồng vào mạng cục bộ (Hardhat quản lý nội bộ, chúng ta không cần phải bắt đầu bất kỳ quy trình nào).

                        
                          governanceToken = await ethers.getContractFactory("MyToken") implementedToken=đang chờ governanceToken.deploy(); await implementedToken.deployed(); transactionResponse = await implementedToken.delegate(owner.address) await transactionResponse.wait(1) timeLock = await ethers.getContractFactory("TimeLock") implementedTimeLock=đang chờ timeLock.deploy(MIN_DELAY,[],[]); await implementedTimeLock.deployed(); governor = await ethers.getContractFactory("GovernorContract") implementedGovernor=đang chờ governor.deploy(deployedToken.address,deployedTimeLock.address,QUORUM_PERCENTAGE,VOTING_PERIOD,VOTING_DELAY); await implementedGovernor.deployed() box = await ethers.getContractFactory("Box") implementedBox=đang chờ box.deploy() await đã triển khaiBox.deployed()

                        
                      

Tạo đề xuất

Tiếp theo, hãy tạo một đề xuất. Chúng ta truyền giá trị được mã hóa của hàm sẽ được gọi trên hợp đồng Box và các tham số của nó.

Đầu ra của hàm đề xuất là một giao dịch có chứa Mã đề xuất. Tính năng này được sử dụng để theo dõi các đề xuất.

                        
                          const proposalDescription="đề xuất dữ liệu này" let encodedFunctionCall = box.interface.encodeFunctionData("store", [77]) const proposalTx = await implementedGovernor.propose([deployedBox.address],[0],[encodedFunctionCall],proposalDescription);

                        
                      

Đề xuất này nhằm kích hoạt chức năng lưu trữ trên hợp đồng Box với giá trị là 77.

bỏ phiếu

Sau đó, chúng tôi bỏ phiếu cho đề xuất này, với số phiếu "1" biểu thị sự chấp thuận.

LƯU Ý: Trong trường hợp này, chúng ta chỉ có một thành viên (chiếm 100% số phiếu) bỏ phiếu.

                        
                          const voteWay = 1 const reason = "Tôi bỏ phiếu đồng ý" let voteTx = await implementedGovernor.castVoteWithReason(proposalId, voteWay, reason)

                        
                      

Hàng đợi và thực hiện

Tiếp theo, bất kỳ thành viên nào từ DAO đều có thể xếp hàng và thực hiện đề xuất và nếu đề xuất được thông qua bỏ phiếu, đề xuất sẽ được thực hiện và hàm lưu trữ trên hợp đồng Box sẽ được gọi với giá trị 77. Bạn có thể đã nhận thấy những thứ như moveTime và moveBlocks. Những thứ này xuất phát từ mẫu Patrick Collins DAO và có thể được sử dụng trong môi trường phát triển để mô phỏng sự trôi qua của thời gian và khai thác khối. Chúng giúp chúng ta mô phỏng việc hoàn thành các giai đoạn bỏ phiếu, trì hoãn khóa thời gian, v.v.

                        
                          const queueTx = await implementedGovernor.queue([deployedBox.address],[0],[encodedFunctionCall],descriptionHash) await queueTx.wait(1) await moveTime(MIN_DELAY + 1) await moveBlocks(1) console.log("Đang thực thi...") const executeTx = await implementedGovernor.execute( [deployedBox.address], [0], [encodedFunctionCall], descriptionHash ) await executeTx.wait(1) const value=await implementedBox.retrieve(); console.log(giá trị)

                        
                      

Chạy thử nghiệm.

Bây giờ chúng ta có thể chạy thử nghiệm bằng lệnh sau.

Kiểm tra mũ bảo hiểm bằng sợi.

Phát hành token cho thành viên mới

Những gì chúng ta thấy ở trên là quá trình của tình huống 1. Đối với kịch bản 2, chúng ta cần phát hành token mới cho các thành viên mới và để họ bỏ phiếu cho các đề xuất.

Mã để phát hành token được hiển thị bên dưới.

                        
                          [chủ sở hữu, addr1, addr2] = chờ ethers.getSigners(); const người ký = chờ ethers.getSigner(addr1.address); const implementedTokenUser2 = chờ implementedToken.connect(người ký) chờ implementedTokenUser2.issueToken(addr1.address,200)

                        
                      

Hàm getSigners() trả về danh sách tất cả các tài khoản trong môi trường phát triển Hardhat, sau đó chúng tôi phát hành 200 mã thông báo tới địa chỉ này.

Thành viên mới bỏ phiếu

Bây giờ chúng ta có một thành viên khác, chúng ta có thể sử dụng thành viên đó để bỏ phiếu, nhưng thành viên mới không thể bỏ phiếu trừ khi anh ta tự thêm mình vào làm đại biểu cho hợp đồng token. Điều này được thực hiện để các thành viên sở hữu token nhưng không muốn tham gia vào quá trình ra quyết định không cần phải chi thêm chi phí gas để duy trì ảnh chụp nhanh về quyền biểu quyết của họ trên sổ cái.

Mã tự ủy quyền như sau.

                        
                          [chủ sở hữu, addr1, addr2] = chờ ethers.getSigners(); const người ký = chờ ethers.getSigner(addr1.address); const implementedTokenUser2 = chờ implementedToken.connect(người ký) chờ implementedTokenUser2.issueToken(addr1.address,200)

                        
                      

Nguồn bài viết: https://blog.blockmagnates.com/how-to-build-a-dao-decentralized-autonomous-organization-in-solidity-af1cf900d95d.

Nhận thêm tài liệu học tập về blockchain thông qua Github! .

https://github.com/Manuel-yang/BlockChainSelfLearning .

Cuối cùng, bài viết này nói về cách thiết lập DAO (tổ chức tự trị phi tập trung) trong Solidity? Bài viết này chỉ có vậy. Bạn có muốn biết thêm về cách xây dựng DAO (tổ chức tự chủ phi tập trung) trong Solidity không? Vui lòng tìm kiếm các bài viết trên CFSDN hoặc tiếp tục duyệt các bài viết liên quan. Tôi hy vọng bạn sẽ ủng hộ blog của tôi trong tương lai! .

26 4 0
Tôi là một chú chim nhỏ
Hồ sơ cá nhân

Tôi là một lập trình viên xuất sắc, rất giỏi!

Nhận phiếu giảm giá Didi Taxi miễn phí
Mã giảm giá Didi Taxi
Giấy chứng nhận ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com