# s11e-DAO **Repository Path**: springnight/s11e-DAO ## Basic Information - **Project Name**: s11e-DAO - **Description**: s11e-DAO,是一个致力于推进bsin-paas产品和生态应用开发的dao组织,社区拥有自己的NFT身份等级、数字积分和NFT交易平台。社区的使命是帮助企业和组织以更低的成本介入区块链价值网络,用区块链技术构建一种更富活力的数字化商业生态模式,进一步实现企业和组织的数字化转型。 - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 2 - **Created**: 2022-06-10 - **Last Updated**: 2022-06-10 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # s11e-DAO ## 介绍 - s11e-DAO,是一个致力于推进 [bsin-paas](https://gitee.com/bsin-paas/all-in-one)产品和生态应用开发的 dao 组织,社区拥有自己的 NFT 身份等级、数字积分和 NFT 交易平台。社区的使命是帮助企业和组织以更低的成本介入区块链价值网络,用区块链技术构建一种更富活力的数字化商业生态模式,进一步实现企业和组织的数字化转型。 - s11e-DAO,也是一个开放式、模块化的DAO框架,旨在帮助DAO组织根据自己的组织形态快速简单灵活的构建自己的组织。 ## 特点 - 模块化 >* s11e-DAO采用**代理-逻辑-控制-数据**分层架构设计,业务逻辑合约与DAO数据状态存储分离,业务逻辑合约以模块化插件合约的形式在s11e-DAO合约中灵活注册。 - 可升级 >* 根据设计,智能合约是不可变的。另一方面,软件质量在很大程度上取决于升级和修补源代码以生成迭代版本的能力。尽管基于区块链的软件从技术的不变性中获益匪浅,但修复错误和潜在的产品改进仍然需要一定程度的可变性。 >* s11e-DAO框架采用非结构化存储代理模式为DAO合约代码提供易于使用、简单、健壮和可选的升级机制来解决这一明显的矛盾,该机制可以由任何类型的治理控制,包括但不限于多重签名钱包、简单地址还是复杂的DAO提案投票机制来实现业务逻辑合约的升级的同时保留了原有链上存储和余额不变。 - 底成本部署 >* 核心合约采用[EIP1167,最小代理合约](https://eips.ethereum.org/EIPS/eip-1167)克隆工厂模式,创建、初始化和添加装饰器到新的DAO,降低DAO创建成本。 - 多态化治理 >* 一旦创建好DAO组织,就可以使用装饰器和扩展对DAO进行扩展和修改。装饰器和扩展通过向 DAO 添加为特定目的而创建的经过严格定义、测试和可扩展的智能合约,可以轻松组装像乐高积木一样的 DAO。装饰器和扩展使 DAO 更加模块化、可升级,并使我们能够共同构建强大的 DAO 工具。它们可以通过 DAO 投票添加到 s11e-DAO。 >* 同时支持独立部署发布的标准化合约:ERC20、ERC721、ERC1155、ERC777 - 多经济模型支持 不同生态和场景下的DAO组织可以使用不同的经济模型,例如: >* [联合曲线(Bonding Curve)](https://zhuanlan.zhihu.com/p/469043282) >>* 联合曲线(Bonding Curve)是一种特殊的数学模型。Token 的流通量与 Token 的价格呈一一对应的函数关系。 >>* 联合曲线合约,是通过买卖函数发行自己的 Token 的合约。要购买 Token ,你需要发送一定量的锚定 Token 到买入函数,该函数以锚定 Token 为计价单位,计算 Token 的平均价格,并向你发送正确数量的 Token 。 >>* 在初始状态下也就是合约中没有锚定 Token 的时候,项目 Token 是没有流动性的。这也意味着,项目 Token 不会凭空产生,而是只有在人参与,注入了锚定 Token 之后, Token 才有流通量。 >>* 此外由于有锚定 Token 的存在,产生的项目 Token 是有一定的价值托底的,因此也不存在虚构交易影响价格的情况。 >* [恒定乘积做市商(uniswap)](https://www.manxinet.com/newest/definance/flowmine/34776.html) >>* 恒定乘积公式是一个简单的规则,它允许任何人立即为一对新资产创建新市场和新AMM。 >>* 为了在两个资产 X 和 Y 之间创建新的乘积 AMM (CPAMM) ,称为流动性提供者(LP)的用户存入这两种资产的x和y储备金。 >>* 这些资产在任何给定时间的比率代表 AMM 上的即时价格。例如,如果 CPAMM 的储备中包含 2,000 USDC 和 1 ETH,则ETH 的瞬时价格将为 2,000 USDC。 >>* 当交易者与 AMM 进行交易时,它会根据公式x * y = k决定给他们什么价格,其中 x 和 y 是储备规模,k 是常数。这意味着其储备规模的乘积在交易期间保持不变(忽略费用)。 - 安全审计,零代码创建DAO >* 合约继承实现安全智能合约的开发库OpenZeppelin,合约安全有保障 >* 项目方无需关注合约代码,通过简单的前端ui click操作,可以实现自己的DAO组织创建,并拥有dao的主页(hotpot) ## 软件架构 ### hardhat - s11e-DAO 基于 Hardhat 进行合约和 dapp 开发 > - Hardhat 是一个方便在以太坊上进行构建的任务运行器。使用它可以帮助开发人员管理和自动化构建智能合约和 dApp 的过程中固有的重复任务,以及轻松地围绕此工作流程引入更多功能。 > - Hardhat 还内置了 Hardhat 网络,Hardhat 网络是为开发而设计的本地以太坊网络。 用来部署合约,运行测试和调试代码 > - Hardhat 还内置了 Hardhat 网络,Hardhat 网络是为开发而设计的本地以太坊网络。 用来部署合约,运行测试和调试代码。 - node设置 >* 安装 cnpm 淘宝镜像: npm install -g cnpm --registry=https://registry.npm.taobao.org >* 将npm设置为淘宝镜像: npm config set registry https://registry.npm.taobao.org >* 通过npm查看cnpm镜像设置: npm config get registry >* 通过cnpm查看cnpm镜像设置:(相当于使用cnpm) cnpm config get registry - hardhat入门 >* 安装 ~~~bash npm install --save-dev ethereum-waffle npm install --save-dev @nomiclabs/hardhat-waffle npm install --save-dev chai npm install --save-dev ethers # 安装Hardhat Upgrades插件 npm install --save-dev @openzeppelin/hardhat-upgrades ~~~ >* 部署 ~~~shell npx hardhat run scripts/demo-deploy.js --network local ~~~ >* 测试 ~~~shell npx hardhat test test/demo.test.js --network local ~~~ ### 代理-逻辑-控制-数据分层架构设计 ![](./doc/assets/frame.png) - 代理层使用智能合约代理模式部署合约,对于业务逻辑(插件)合约升级时,只需要部署新的业务逻辑合约,然后将新合约的地址注册到代理合约中,即可完成合约升级,并且对外提供服务的合约地址不变。 - 逻辑层采用采用插件模式,所有业务组件可根据 DAO 组织扩展插件以实现相应的业务需求 - 数据管理控制层使用的是 OpenZeppelin 提供的“非结构化存储实现可升级”的代理框架,以装饰器的形式提供 DAO 状态的的数据状态读写访问,同时控制对访问控制权限进行校验 - 数据层存储 DAO 组织的状态数据,成员信息,合约地址等所有数据信息 - 访问控制层(ACL): * 所有更改s11eDAO状态的的操作都经过访问标志来实现,以保证数据的安全性 * 访问标志有 3 个主要类别: * 会员标志:EXISTS. * 提案标志:EXISTS, SPONSORED, PROCESSED. * AclFlag: REPLACE_WRAPPER, SUBMIT_PROPOSAL, UPDATE_DELEGATE_KEY, SET_CONFIGURATION, ADD_EXTENSION, REMOVE_EXTENSION, NEW_MEMBER. * daoFactory.addWrappers当函数被调用传递新的适配器时,每个适配器的访问标志必须提供给 DAOFactory 。这些标志将授予对 S11eDao 合约的访问权限,并且必须执行相同的过程来授予每个适配器对每个扩展(函数daoFactory.configureExtension)的访问权限。 * 访问标志使用修饰符在 S11eDao 中定义hasAccess。例如,带有修饰符的函数hasAccess(this, AclFlag.REPLACE_WRAPPER)意味着调用该函数的适配器需要REPLACE_WRAPPER启用访问标志,否则调用将恢复。为了创建具有正确访问标志的适配器,首先需要映射适配器将在 S11eDao 和扩展中调用的所有函数,并使用如上所述的 DAO 工厂提供这些访问标志。 ### 工程结构 核心(core)合约通过装饰器(wrapper)合约提供读写访问接口,采用可扩展装卸的插件(extensions)合约模式简化DAO状态更改的复杂性,简化s11e核心合约,本质上,插件类似于核心合约的扩展适配器,他可以被多个装饰器和s11eDao使用,用来增强DAO功能和状态管理,而不会扰乱核心合约。 - 核心合约(core) * s11e-DAO 的框架支柱,存储 DAO 的状态数据,提供装饰器合约绑定,业务罗家插件合约的注册功能,创建 dao 组织接口。 - 装饰器合约(wrapper) * wrapper用于实现 DAO 状态和数据访问控制业务逻辑 >* wrapper不跟踪 DAO 的状态。wrapper可能使用存储来控制自己的状态,但理想情况下,任何 DAO 状态更改都必须传播到 S11eDao 核心合约。 >* wrapper只是执行智能合约逻辑,通过调用 S11eDao 来改变 DAO 的状态。他们还可以编写与外部世界、其他wrapper甚至扩展交互的复杂调用,以提取/推送附加信息。 >* wrapper必须遵循模板wrapper定义的规则。 * eg. * ConfigurationWrapper: 管理存储和检索共享装饰器所需的每个 DAO 设置 * DistributeWrapper: 允许成员将资金分发给 DAO 的一个或所有成员 * FinancingWrapper: 允许个人和/或组织申请资金来资助他们的项目,DAO 的成员有权投票决定应该资助哪些项目。 * GuildKickWrapper: 让成员可以自由选择哪些个人或组织真正应该成为 DAO 的一部分。 * ManagingWrapper: 通过投票过程添加/更新/移除 DAO 装饰器来完善 DAO 功能。 * 创建提案来替换、移除、添加一个wrapper >* OffchainVotingWrapper: 将链下投票治理流程添加到 DAO 以支持无气体投票。 >* OnboardingWrapper: 触发以固定价格铸造内部代币以换取特定代币的过程。 >* RagequitWrapper: 让成员可以自由选择何时是出于任何给定原因退出 DAO 的最佳时间。 >* TributeWrapper: 允许潜在的和现有的 DAO 成员向 DAO 贡献任意数量的 ERC-20 代币,以换取任意数量的 DAO 内部代币。 >* TributeNftWrapper: 允许潜在的 DAO 成员向 DAO 贡献注册的 ERC-721 资产,以换取任何数量的 DAO 单位。 >* VotingWrapper: 将简单的链上投票治理流程添加到 DAO。 >* WithdrawWrapper: 允许成员从 DAO 银行提款。 - 插件合约(extensions) >* DAO功能和状态管理的扩展,代理方式升级更新 * eg. * BankExtension:为s11eDAO添加银行功能,并跟踪DAO账户和内部代币余额 * NftExtension:为s11eDAO添加管理和策划标准NFT集合的能力 * FtExtension:为s11eDAO添加了在成员和外部账户之间管理和转移内部代币的功能 * ExcutorExtension:使用EVM指令向DAO添加执行对其他合约的委托调用的功能,包括不属于DAO合约的delegatecall - 工具合约(utils) >* 数学安全计算 >* 访问控制管理 >* 公共函数 >* ## 部署教程 ### Hardhat - 创建一个新的 Hardhat 项目 > - Node.js >= 12.0 > - 创建 Hardhat 项目 ```shell npm init --yes npm install --save-dev hardhat npx hardhat # 使用键盘选择 “创建一个新的hardhat.config.js(Create an empty hardhat.config.js)”,然后回车 ``` ### 编写和编译智能合约 - 创建一个名为 contracts 的新目录,根据上述框架设计中的目录结构,创建合约文件 ```shell mkdir -p contracts/core contracts/wrapper contracts/extensions/bank contracts/utils touch contracts/core/S11eDaoFactory.sol contracts/wrapper/BankWrapper.sol contracts/extensions/bank/BankExtension.sol contracts/utils/Signatures.sol ``` - openzeppelin OpenZeppelin Contracts 是一个用于安全智能合约开发的库。 > - 它提供了 ERC20 和 ERC721 等标准的实现,您可以按需部署或扩展以满足您的需求,还提供 Solidity 组件来构建自定义合同和更复杂的分散系统。 - 安装 openzeppelin ```shell npm install --save-dev @openzeppelin/contracts ``` - 安装Hardhat Upgrades插件: ~~~shell npm install --save-dev @openzeppelin/hardhat-upgrades ~~~ - 我们使用ethers,所以还需要安装: ~~~shell npm install --save-dev @nomiclabs/hardhat-ethers ethers ~~~ ## demo使用说明 部署合约前先启动本地节点 - 可升级合约 >* 部署合约Demo ~~~shell $ npx hardhat run scripts/demo-deploy.js --network local 0xc0601C869abdf083368900A32aF6E3aBB1933C02 ~~~ >* 与Demo合约进行交互测试 创建 demo.test.js >* 执行测试 ~~~shell $ npx hardhat test test/demo.test.js --network local ~~~ >* 执行可升级合约部署 ~~~shell $ npx hardhat run scripts/demo-upgradeable-deploy.js --network local Deploying Demo... Demo to: 0x959922bE3CAee4b8Cd9a407cc3ac1C251C2007B1 ~~~ >* 部署完成后 我们需要保存我们的合约地址,这个地址以后就是面向用户的合约交互地址,每次升级合约都需要这个地址作为代理合约地址与新升级的合约进行绑定 >* 开始编写升级合约DemoV2.sol 对升级的合约增加了increment方法 每次调用score分值加1 >* 开始编写部署升级合约的文件:demo-upgrade.js >* 执行合约升级 ~~~shell $ npx hardhat run scripts/demo-upgrade.js --network local ~~~ >* 通过hardhat控制台验证升级合约 ~~~shell $ npx hardhat console --network local const upgradeContractName = 'DemoV2' const proxyContractAddress = '0x959922bE3CAee4b8Cd9a407cc3ac1C251C2007B1' const Demo = await ethers.getContractFactory(upgradeContractName) const demo = await Demo.attach(proxyContractAddress) await demo.increment() (await demo.socre()).toString() ~~~ >* 针对升级合约编写测试用例:demo-v2.test.js 注意事项: - 可升级合约 不能包含construct构造函数,构造函数的实现方式是通过调用普通函数实现的 - 因此针对普通函数 可以通过权限控制调用机制比如增加普通函数只允许合约部署者调用 ### [Upgradeable合约](https://zhuanlan.zhihu.com/p/436100395) 使用OpenZeppelin Upgrades #### hardhat快速升级-UpgradeableErc20 #### 独立部署升级-UpgradeableLogic - 部署 >* 首先部署[LogicV1 逻辑合约](./contracts/test_upgradeable/UpgradeableLogic.sol),得到地址:0x111 >* 然后部署[ProxyAdmin 管理合约](./node_modules/@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol),用于升级逻辑合约,得到地址:0x222 >* 接下来部署[TransparentUpgradeableProxy 代理合约](./contracts/test_upgradeable/TransparentUpgradeableProxy.sol),用于存储逻辑合约数据,得到地址:0x333 - 升级 上述部署之后,可升级合约已经部署完成,开始测试 此处应调用代理合约而不是直接调用业务合约 >* 首先选中业务合约,使用At Address填入代理合约地址(0x333)后生成已代理的可升级合约 ### S11eDao 部署 - 克隆工厂模式部署说明 * 部署流程: * 1.先部署 **S11eDao** 合约,得到地址:0x... * 2.再部署 **S11eDaoFactory** 合约,构造参数为1中得到地址:0x... * 3.调用 **S11eDaoFactory** 合约的 **createDao** 方法,创建S11eDao新合约 * 4.调用 **S11eDaoFactory** 合约的 **getDaoAddress(string calldata _daoName)** 方法,可根据DAO名称获取DAO合约地址:0x... ## 设计参考 - [tributeDAO](https://github.com/openlawteam/tribute-contracts) - [evidenceContract](https://github.com/six-days/ethereum-contracts/tree/master/evidence) - [] ## front工程 ### 创建front工程 - 使用bsin-paas react前端脚手架创建工程 ~~~bash mkdir front cp -r bsin-ui-scaffold-react/* ./front/ cd front yarn ~~~ - 导入web3uikit ~~~bash yarn add web3uikit ~~~