经济下行阶段,一个 37 岁失业程序员的独白(经历/经验分享)
警告:区块链投资高风险,需要谨慎,谨慎,再谨慎!
实战案例四:DeFi 去中心化交易所
现实情况是期望代币可以在去中心化的交易场所中交换,这篇文章就是从一个简单案例来说明交换,流动性该如何实现。 我们需要先梳理一下,期望这个应用具备哪些功能:只用一个代币对建立交易场所交易收取 1% 的费用用户可以为 UseWeb3Token 添加或删除流动性为用户提供 LP 代币说明:实现会比这个例子复杂的多// SPDX-License-Identifier: SEE LICENSE IN LICENSE pragma solidity ^0.8.4; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; contract UseWeb3Exchange is ERC20 { address public useweb3TokenAddress; constructor(address useweb3TokenContract) ERC20("LP Token", "LP") { useweb3TokenAddress = useweb3TokenContract; } function getReserve() publ...
初识 Solidity 和 OpenZeppelin
Solidity 是一种面向对象的高级静态语言,用于实现智能合约,运行于 以太坊虚拟机,它支持继承,库和自定义类型等。pragma solidity ^0.8.0; contract HelloWorld { } Solidity 有三种类型的变量,熟悉它是因为变量的范围是由它们声明的位置所决定的:Local在函数内部声明且不存储在区块链上State存储在区块链上Global提供区块链相关的信息,它在运行时由以太坊虚拟机注入包括交易发送者,区块时间戳,区块哈希等全局变量语法知识,请阅读:https://docs.soliditylang.org/en/v0.8.9/index.html初识 OpenZeppelin说明:OpenZeppelin 是一家以太坊安全公司,其为流行的智能合约标准开发了一组合约,这些合约经过了大量的测试和安全审查,所以如果我们需要实现这些标准合约时,应该尝试找到 OpenZeppelin 提供的合约,而不是重头开始重写整个标准。https://github.com/OpenZeppelin/openzeppelin-contracts在 useweb3 ...
Dev
经济下行阶段,一个 37 岁失业程序员的独白(经历/经验分享)
警告:区块链投资高风险,需要谨慎,谨慎,再谨慎!
实战案例四:DeFi 去中心化交易所
现实情况是期望代币可以在去中心化的交易场所中交换,这篇文章就是从一个简单案例来说明交换,流动性该如何实现。 我们需要先梳理一下,期望这个应用具备哪些功能:只用一个代币对建立交易场所交易收取 1% 的费用用户可以为 UseWeb3Token 添加或删除流动性为用户提供 LP 代币说明:实现会比这个例子复杂的多// SPDX-License-Identifier: SEE LICENSE IN LICENSE pragma solidity ^0.8.4; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; contract UseWeb3Exchange is ERC20 { address public useweb3TokenAddress; constructor(address useweb3TokenContract) ERC20("LP Token", "LP") { useweb3TokenAddress = useweb3TokenContract; } function getReserve() publ...
初识 Solidity 和 OpenZeppelin
Solidity 是一种面向对象的高级静态语言,用于实现智能合约,运行于 以太坊虚拟机,它支持继承,库和自定义类型等。pragma solidity ^0.8.0; contract HelloWorld { } Solidity 有三种类型的变量,熟悉它是因为变量的范围是由它们声明的位置所决定的:Local在函数内部声明且不存储在区块链上State存储在区块链上Global提供区块链相关的信息,它在运行时由以太坊虚拟机注入包括交易发送者,区块时间戳,区块哈希等全局变量语法知识,请阅读:https://docs.soliditylang.org/en/v0.8.9/index.html初识 OpenZeppelin说明:OpenZeppelin 是一家以太坊安全公司,其为流行的智能合约标准开发了一组合约,这些合约经过了大量的测试和安全审查,所以如果我们需要实现这些标准合约时,应该尝试找到 OpenZeppelin 提供的合约,而不是重头开始重写整个标准。https://github.com/OpenZeppelin/openzeppelin-contracts在 useweb3 ...
Dev

Subscribe to icepy

Subscribe to icepy
<100 subscribers
<100 subscribers
Share Dialog
Share Dialog
DAO 代表了去中心化自治组织,从本质上讲 DAO 允许成员创建提案并对提案进行投票,用投票结果来触发代码,执行决策。
这个例子我们需要使用到之前写好的 UseWeb3NFT,一个成员可能有一个 UseWeb3NFT 也许有多个 UseWeb3NFT,但总的来说,我们可以视一个 UseWeb3NFT 为一票,DAO成员可以进行投票。
在实际编码之前,我们先来梳理一下这个例子想要完成的需求:
只有 DAO 成员可以创建提案
DAO 成员可以对提案进行投票
提案有一个截止时间
在截止时间之后任何 DAO 成员都可以执行投票结果
说明:这只是一个案例,真实情况会比这复杂的多
接下来我们会开始编写 UseWeb3DAO 合约,这是一个相对复杂的合约,可能需要一些解释。
首先,我们需要先定义 UseWeb3NFT 和 UseWeb3FakeNFTMarketplace 的接口,因为我们的构造函数会使用它。
interface IUseWeb3NFT{
function balanceOf(address owner) external view returns (uint256);
}
interface IUseWeb3FakeNFTMarketplace{
function available(uint256 _tokenId) external view returns (bool);
function purchase(uint256 _tokenId) external payable;
function price() external view returns(uint256);
}
接下来,我们需要使用 struct 关键字来定义提案的数据结构:
struct Proposal {
// 提案 id
uint256 id;
// 如果提案通过,购买 NFT 的tokenId
uint256 tokenId;
// 投赞成票的数量
uint256 yesVotes;
// 投反对票的数量
uint256 noVotes;
// 截止日期
uint256 deadline;
// 提案是否被执行
bool executed;
// 记录已经投过票的 Address map
mapping(address => bool) voters;
}
这个数据结构,是我们这个例子 DAO 的基础,所有的操作都会依赖它
当然我们也需要对一些条件进行验证,比如只允许 NFT 支持者才能投票和创建提案
modifier onlyHolder {
require(useweb3NFT.balanceOf(msg.sender) > 0, "Not Holder");
_;
}
modifier onlyActive(uint256 proposalIndex) {
require(proposals[proposalIndex].deadline > block.timestamp, "DEADLINE EXCEEDED");
_;
}
modifier onlyInactive(uint256 proposalIndex) {
require(proposals[proposalIndex].deadline <= block.timestamp, "DEADLINE NOT EXCEEDED");
require(proposals[proposalIndex].executed == false,"PROPOSAL ALREADY EXECUTED");
_;
}
创建提案的方法:
function createProposal(uint256 _tokenId) external onlyHolder returns(uint256){
require(useweb3FakeNFTMarketplace.available(_tokenId), "Not Sale");
uint256 proposalId = _proposalId.current();
Proposal storage proposal = proposals[numberProposals];
proposal.id = proposalId;
proposal.tokenId = _tokenId;
proposal.deadline = block.timestamp + 5 minutes;
_proposalId.increment();
numberProposals = _proposalId.current();
return numberProposals - 1;
}
对提案进行投票的方法:
function voteOn(uint256 proposalIndex, Vote vote) external onlyHolder onlyActive(proposalIndex){
Proposal storage proposal = proposals[proposalIndex];
uint256 votes = useweb3NFT.balanceOf(msg.sender);
require(!proposal.voters[msg.sender], "VOTED");
require(votes > 0, "ALREADY VOTED");
// 根据投票的枚举对投票数量进行累加
if (vote == Vote.Y) {
proposal.yesVotes += votes;
} else {
proposal.noVotes += votes;
}
proposal.voters[msg.sender] = true;
}
执行提案的方法:
function execute(uint256 proposalIndex) external onlyHolder onlyInactive(proposalIndex){
Proposal storage proposal = proposals[proposalIndex];
if (proposal.yesVotes > proposal.noVotes){
// 赞同票大于反对票时,先检查本合约中有没有足够的 eth
uint256 price = useweb3FakeNFTMarketplace.price();
require(address(this).balance >= price, "costs 0.01 ether");
// 去市场购买
useweb3FakeNFTMarketplace.purchase{value: price}(proposal.tokenId);
}
// 确定提案已经被执行
proposal.executed = true;
}
DAO 代表了去中心化自治组织,从本质上讲 DAO 允许成员创建提案并对提案进行投票,用投票结果来触发代码,执行决策。
这个例子我们需要使用到之前写好的 UseWeb3NFT,一个成员可能有一个 UseWeb3NFT 也许有多个 UseWeb3NFT,但总的来说,我们可以视一个 UseWeb3NFT 为一票,DAO成员可以进行投票。
在实际编码之前,我们先来梳理一下这个例子想要完成的需求:
只有 DAO 成员可以创建提案
DAO 成员可以对提案进行投票
提案有一个截止时间
在截止时间之后任何 DAO 成员都可以执行投票结果
说明:这只是一个案例,真实情况会比这复杂的多
接下来我们会开始编写 UseWeb3DAO 合约,这是一个相对复杂的合约,可能需要一些解释。
首先,我们需要先定义 UseWeb3NFT 和 UseWeb3FakeNFTMarketplace 的接口,因为我们的构造函数会使用它。
interface IUseWeb3NFT{
function balanceOf(address owner) external view returns (uint256);
}
interface IUseWeb3FakeNFTMarketplace{
function available(uint256 _tokenId) external view returns (bool);
function purchase(uint256 _tokenId) external payable;
function price() external view returns(uint256);
}
接下来,我们需要使用 struct 关键字来定义提案的数据结构:
struct Proposal {
// 提案 id
uint256 id;
// 如果提案通过,购买 NFT 的tokenId
uint256 tokenId;
// 投赞成票的数量
uint256 yesVotes;
// 投反对票的数量
uint256 noVotes;
// 截止日期
uint256 deadline;
// 提案是否被执行
bool executed;
// 记录已经投过票的 Address map
mapping(address => bool) voters;
}
这个数据结构,是我们这个例子 DAO 的基础,所有的操作都会依赖它
当然我们也需要对一些条件进行验证,比如只允许 NFT 支持者才能投票和创建提案
modifier onlyHolder {
require(useweb3NFT.balanceOf(msg.sender) > 0, "Not Holder");
_;
}
modifier onlyActive(uint256 proposalIndex) {
require(proposals[proposalIndex].deadline > block.timestamp, "DEADLINE EXCEEDED");
_;
}
modifier onlyInactive(uint256 proposalIndex) {
require(proposals[proposalIndex].deadline <= block.timestamp, "DEADLINE NOT EXCEEDED");
require(proposals[proposalIndex].executed == false,"PROPOSAL ALREADY EXECUTED");
_;
}
创建提案的方法:
function createProposal(uint256 _tokenId) external onlyHolder returns(uint256){
require(useweb3FakeNFTMarketplace.available(_tokenId), "Not Sale");
uint256 proposalId = _proposalId.current();
Proposal storage proposal = proposals[numberProposals];
proposal.id = proposalId;
proposal.tokenId = _tokenId;
proposal.deadline = block.timestamp + 5 minutes;
_proposalId.increment();
numberProposals = _proposalId.current();
return numberProposals - 1;
}
对提案进行投票的方法:
function voteOn(uint256 proposalIndex, Vote vote) external onlyHolder onlyActive(proposalIndex){
Proposal storage proposal = proposals[proposalIndex];
uint256 votes = useweb3NFT.balanceOf(msg.sender);
require(!proposal.voters[msg.sender], "VOTED");
require(votes > 0, "ALREADY VOTED");
// 根据投票的枚举对投票数量进行累加
if (vote == Vote.Y) {
proposal.yesVotes += votes;
} else {
proposal.noVotes += votes;
}
proposal.voters[msg.sender] = true;
}
执行提案的方法:
function execute(uint256 proposalIndex) external onlyHolder onlyInactive(proposalIndex){
Proposal storage proposal = proposals[proposalIndex];
if (proposal.yesVotes > proposal.noVotes){
// 赞同票大于反对票时,先检查本合约中有没有足够的 eth
uint256 price = useweb3FakeNFTMarketplace.price();
require(address(this).balance >= price, "costs 0.01 ether");
// 去市场购买
useweb3FakeNFTMarketplace.purchase{value: price}(proposal.tokenId);
}
// 确定提案已经被执行
proposal.executed = true;
}
No activity yet