- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
本文将帮助您理解 DAO 的概念,并帮助您构建一个基本的 DAO.
您可以将 DAO 视为基于互联网的实体(比如企业),由其股东(拥有代币和比例投票权的成员)共同拥有和管理。在 DAO 中,决策是通过提案做出的,DAO 的成员可以对这些提案进行投票,然后执行它们.
DAO 完全由可公开查看/可验证的代码管理,没有一个人(如 CEO)负责决策.
如前所述,DAO 由代码管理,但是如果运行代码的机器的人决定关闭机器或编辑代码怎么办?
所需要的是让相同的代码在由不同实体托管的一组机器上运行,这样即使其中一个关闭,另一个也可以接管。区块链帮助我们解决了上述问题,基于 EVM 的区块链(如 Ethereum 和 Polygon)允许我们在公共去中心化分类账上运行智能合约。部署在这些网络上的智能合约将传播到网络上所有可以查看和验证它的节点,并且没有任何一方控制网络.
具有代币成员资格的 DAO 向其成员发行代币,代币代表系统中的投票权。根据所设置的治理,任何人都可以创建 DAO 更改提案,并将其提交给具有法定人数(通过所需的最低百分比/票数)和投票持续时间的投票。成员可以对提案进行查看和投票,投票权与成员拥有的代币数量成正比。投票期结束后,我们检查提案是否通过,如果通过,则执行.
DAO 的一些示例是 MakerDAO 和 Aragon .
下图显示了流程.
我们将在我们的代码库中使用 OpenZeppelin 合约,我还将使用 Patrick Collins 的 DAO 模板 中的一些代码.
您将需要以下内容才能开始.
我已经编写代码并将其推送到 GitHub,如果您想自己尝试,可以在 此处 获取代码,不过我建议您留下来,因为我会解释代码.
我们将构建一个将执行以下操作的 DAO:
场景 1 。
场景 2 。
如前所述,我们将使用 OpenZeppelin 的治理合约。合同如下:
让我们开始把这一切放在一起。使用 Hardhat 创建一个空的示例项目。在您的终端中运行以下命令.
yarn add — 开发安全帽 。
接下来,让我们使用 hardhat 创建我们的文件夹结构.
你应该看到这样的提示 。
单击“创建基本示例项目”。该过程完成后,您应该会看到类似这样的内容.
让我们开始添加合约,首先让我们添加 GovernorContract。 我们可以从OpenZeppelin 获得相同的代码,或者您可以复制下面的代码或从我的仓库中复制代码。我的合约代码修复了 OpenZeppelin 版本中的一个 问题 ,以及投票延迟、法定人数和投票周期的参数化,类似于 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 is 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)
{}
// The following functions are overrides required by 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
view
override(IGovernor, GovernorVotesQuorumFraction)
returns (uint256)
{
return super.quorum(blockNumber);
}
function getVotes(address account, uint256 blockNumber)
public
view
override(Governor, IGovernor)
returns (uint256)
{
return _getVotes(account, blockNumber, _defaultParams());
}
function state(uint256 proposalId)
public
view
override(Governor, GovernorTimelockControl)
returns (ProposalState)
{
return super.state(proposalId);
}
function propose(address[] memory targets, uint256[] memory values, bytes[] memory calldatas, string memory description)
public
override(Governor, IGovernor)
returns (uint256)
{
return super.propose(targets, values, calldatas, description);
}
function proposalThreshold()
public
view
override(Governor, GovernorSettings)
returns (uint256)
{
return super.proposalThreshold();
}
function _execute(uint256 proposalId, address[] memory targets, uint256[] memory values, bytes[] memory calldatas, bytes32 descriptionHash)
internal
override(Governor, GovernorTimelockControl)
{
super._execute(proposalId, targets, values, calldatas, descriptionHash);
}
function _cancel(address[] memory targets, uint256[] memory values, bytes[] memory calldatas, bytes32 descriptionHash)
internal
override(Governor, GovernorTimelockControl)
returns (uint256)
{
return super._cancel(targets, values, calldatas, descriptionHash);
}
function _executor()
internal
view
override(Governor, GovernorTimelockControl)
returns (address)
{
return super._executor();
}
function supportsInterface(bytes4 interfaceId)
public
view
override(Governor, GovernorTimelockControl)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
}
接下来,让我们添加令牌合约,这在 OpenZeppelin 上也是可用的。我的代码有一个额外的“issueToken”函数(稍后会详细介绍).
// 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 is ERC20, ERC20Permit, ERC20Votes {
constructor() ERC20("MyToken", "MTK") ERC20Permit("MyToken") {
_mint(msg.sender, 1000);
}
// The functions below are overrides required by Solidity.
function _afterTokenTransfer(address from, address to, uint256 amount)
internal
override(ERC20, ERC20Votes)
{
super._afterTokenTransfer(from, to, amount);
}
function _mint(address to, uint256 amount)
internal
override(ERC20, ERC20Votes)
{
super._mint(to, amount);
}
function _burn(address account, uint256 amount)
internal
override(ERC20, ERC20Votes)
{
super._burn(account, amount);
}
function issueToken(address to, uint256 amount) public{
_mint(to, amount);
}
}
最后,让我们检查一下 Target 合约,在我们的例子中,我们将使用 Patrick Collins 使用的相同 Box 合约.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/governance/TimelockController.sol";
contract TimeLock is TimelockController {
// minDelay is how long you have to wait before executing
// proposers is the list of addresses that can propose
// executors is the list of addresses that can execute
constructor(
uint256 minDelay,
address[] memory proposers,
address[] memory executors
) TimelockController(minDelay, proposers, executors) {}
}
现在我们有了合同,我们需要编写测试。在“test”文件夹下创建一个文件“sample-test.js”。让我们开始编写我们的测试。首先,让我们使用以下数据创建一个名为“helper.config.js”的配置文件.
module.exports=
{
MIN_DELAY:3600,
QUORUM_PERCENTAGE:90,
VOTING_PERIOD:5,
VOTING_DELAY:3,
ADDRESS_ZERO :"0x0000000000000000000000000000000000000000"
}
法定人数为 90%,投票周期为 5 个区块,投票延迟为 3 个区块。TimeLock 的最小延迟为 3600 秒.
让我们编写代码将所有合约部署到本地网络(Hardhat 在内部管理它,我们不需要启动任何进程) 。
governanceToken = await ethers.getContractFactory("MyToken")
deployedToken=await governanceToken.deploy();
await deployedToken.deployed();
transactionResponse = await deployedToken.delegate(owner.address)
await transactionResponse.wait(1)
timeLock = await ethers.getContractFactory("TimeLock")
deployedTimeLock=await timeLock.deploy(MIN_DELAY,[],[]);
await deployedTimeLock.deployed();
governor = await ethers.getContractFactory("GovernorContract")
deployedGovernor=await governor.deploy(deployedToken.address,deployedTimeLock.address,QUORUM_PERCENTAGE,VOTING_PERIOD,VOTING_DELAY);
await deployedGovernor.deployed()
box = await ethers.getContractFactory("Box")
deployedBox=await box.deploy()
await deployedBox.deployed()
接下来,创建提案。我们传递将在 Box 合约及其参数上调用的函数的编码值.
propose 函数的输出是一个包含 Proposal Id 的交易。 这用于跟踪提案.
const proposalDescription="propose this data"
let encodedFunctionCall = box.interface.encodeFunctionData("store", [77])
const proposeTx = await deployedGovernor.propose([deployedBox.address],[0],[encodedFunctionCall],proposalDescription);
提案是在值为 77 的 Box 合约上触发 存储功能.
然后我们对该提案进行投票,投票“1”表示同意.
注意: 在这种情况下,我们只有一名成员(拥有 100% 的选票)在投票.
const voteWay = 1
const reason = "I vote yes"
let voteTx = await deployedGovernor.castVoteWithReason(proposalId, voteWay, reason)
接下来,来自 DAO 的任何成员都可以排队并执行该提案,如果提案通过投票,它将被执行,并且 Box 合约上的存储函数将被调用,值为 77。你可能已经注意到像 moveTime 和 moveBlocks , 这些来自 Patrick Collins DAO 模板 ,在开发环境中可用于模拟时间的流逝和区块挖掘,它们帮助我们模拟投票期的完成、时间锁定延迟等.
const queueTx = await deployedGovernor.queue([deployedBox.address],[0],[encodedFunctionCall],descriptionHash)
await queueTx.wait(1)
await moveTime(MIN_DELAY + 1)
await moveBlocks(1)
console.log("Executing...")
const executeTx = await deployedGovernor.execute(
[deployedBox.address],
[0],
[encodedFunctionCall],
descriptionHash
)
await executeTx.wait(1)
const value=await deployedBox.retrieve();
console.log(value)
运行测试 。
我们现在可以使用以下命令运行测试 。
纱线安全帽测试 。
我们上面看到的是场景 1 的流程。对于场景 2,我们需要向新成员发行新代币并让他们对提案进行投票.
发行代币的代码如下所示 。
[owner, addr1, addr2] = await ethers.getSigners();
const signer=await ethers.getSigner(addr1.address);
const deployedTokenUser2=await deployedToken.connect(signer)
await deployedTokenUser2.issueToken(addr1.address,200)
函数 getSigners() 返回 Hardhat 开发环境中所有帐户的列表,然后我们向该地址发行 200 个令牌.
现在我们有了另一个成员,我们可以用他来投票,但是新成员不能投票,除非他首先将自己添加为代币合约的代表,这样做是为了让拥有代币但不想参与决策的成员不需要花费额外的 gas 成本来维护他们在账本上的投票权快照.
自委托的代码如下.
[owner, addr1, addr2] = await ethers.getSigners();
const signer=await ethers.getSigner(addr1.address);
const deployedTokenUser2=await deployedToken.connect(signer)
await deployedTokenUser2.issueToken(addr1.address,200)
文章来源: https://blog.blockmagnates.com/how-to-build-a-dao-decentralized-autonomous-organization-in-solidity-af1cf900d95d 。
通过Github 获取更多区块链学习资料! 。
https://github.com/Manuel-yang/BlockChainSelfLearning 。
最后此篇关于如何在Solidity中建立DAO(去中心化自治组织)?的文章就讲到这里了,如果你想了解更多关于如何在Solidity中建立DAO(去中心化自治组织)?的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我是 Django 新手并开始了一个项目,我想以正确的方式去做。 我想知道您认为组织项目的最佳实践是什么。 以下是我的一些问题: 如何将静态资源与 Python 代码分开,以免浪费时间通过 Djang
通过这个组织,是否可以引用“id”属性? function house(id) { this.id = id } house.prototype.buy = function() { }
我的任务是“识别并修复任何错误”。这张取自 Java 教科书的图片显示了 Swing 结构的组织。这对我来说很好,我没有发现任何问题。 谁能解释一下? JPanel 应该放在 JComponent 之
重要的事情 是否可以确定 WHERE 条件的最佳顺序以使其更快?例如,我有一个包含 6 个条件的查询。一些简单,另一些带有子查询或函数。我的想法是对查询进行概要分析,以确定条件语句 true 的常见程
我有 Java/AS3/Javascript 背景,我的所有类都组织成包,以帮助表示它们的功能。 在开始一个 C++ 项目时,我试图以几乎相同的方式模仿这个文件系统结构,但我一直遇到包含问题。 目前我
我正在使用 CKAN 作为开放数据门户。我已经完成了 CKAN 实例的设置并添加了数据集、组和组织。 主页上有一个特色组和一个特色组织框。如何在主页上显示我想要的组和组织。 如何在主页上更改这些特色组
我已经创建了我的第一个 iPhone 应用程序,它可以在表格 View 中显示类似类型的音轨。用户可以使用类似 ipod 的控件来播放音轨,这些控件可以流式传输 mp3。 我的所有代码都在两个主要类中
我将我的代码组织成 20-60 行模块,通常采用模块模式。我想要一个结构良好的面向对象的 JavaScript 库。 这是最好的方法吗?代码已经过测试并且有效。 我喜欢它,因为程序员可以从库中提取模块
我正在使用 riot.js 和 jquery 构建一个应用程序。一切都按预期工作,但是随着代码的增长,我也担心在代码中随机/意外的地方触发和处理事件 (.trigger/.on) 对保持我的代码有条理
这是另一个 GIT 新手。 我想在我们的项目中使用 GIT。 团队不熟悉 GIT。 这些项目基本上由一些通用项目(*)和一些应用项目组成。应用程序正在使用公地,公地也可以使用其他公地。通过“使用”我的
例如,考虑一个组织有一个包含两个分支的存储库的情况,master 和 1.0.0.1。 是否可以让团队对 master 具有只读访问权限,而对分支 (1.0.0.1) 具有读写访问权限? 最佳答案 自
我一直致力于寻找组织 CSS 代码的最佳方式,尤其是在大型网站上。我对编写风格不太感兴趣,而对人们如何构建和管理他们的代码更感兴趣。 我一直在遵循这个结构,我觉得它在可维护性方面工作得很好,但我想听取
我们正在扩展到一个大型微服务构建,并通过 postman 完成更多测试(现场验证、错误测试等)。好奇...您的团队如何组织大量 API 的集合? (按 API、按测试类型、按发布等)从一个团队传递到另
我最近遇到了这个编码面试问题,但似乎找不到答案。这是问题。 给定一个整数数组,编写一个函数,返回组织数组所需的最小交换,使得相邻元素的绝对差都小于或等于 K。交换可以是任意两个数组元素,不一定是相邻的
我有 100 多页。所有页面都使用不同的模板。 目前,我有一长串 .state('page.html').state('page2.html') 等。10-15 页后,我认为这变得不可读/难以管理。
我看下grails-app/i18n有一吨messages*.properties捆绑。我想将我的应用程序国际化,但每页有 1 个“捆绑集”。我所说的包集是指包含相同文本但用于不同语言的一组包/属性文
我正在编写一个非常非常长的 CUDA 内核,它对人类的可读性来说非常糟糕。有什么方法可以用内核外部的功能组织 CUDA 内核吗?示例: __global__ void CUDA_Kernel(int*
我的公司要求我将Outlook用于我的电子邮件。 Outlook几乎不执行我想做的任何事情,这让我感到非常沮丧。 (我并不是要在这里发动一场火焰大战,它必须完全执行数千名CEO想要做的事情,但我不是C
我一直在尝试一些不同的方法来组织我的 javascript 应用程序中的代码,我想知道哪种方法最合适。 第一个例子: var Application = { init: function()
Angular 样式指南包含有关在应用程序中使用类和接口(interface)的最佳实践的信息。但它没有任何关于如何组织我的接口(interface)和模型类的信息。 有一个问题:关于文件和类的组织有
我是一名优秀的程序员,十分优秀!