From 9c503c36bc9f833b3ea2bd5fbd54639c9fff67cb Mon Sep 17 00:00:00 2001 From: aahna-ashina <95955389+aahna-ashina@users.noreply.github.com> Date: Sun, 12 Mar 2023 14:21:07 +0800 Subject: [PATCH 01/17] feat: add priority token-gating (erc-721) (#41) closes #41 --- contracts/protocol/Sector3DAO.sol | 4 +- contracts/protocol/Sector3DAOPriority.sol | 11 +++- contracts/token/Sector3Dove.sol | 39 ++++++++++++++ scripts/deploy-nft.ts | 22 ++++++++ test/Sector3DAO.ts | 16 +++--- test/Sector3Priority.ts | 66 +++++++++++++++++++++-- 6 files changed, 144 insertions(+), 14 deletions(-) create mode 100644 contracts/token/Sector3Dove.sol create mode 100644 scripts/deploy-nft.ts diff --git a/contracts/protocol/Sector3DAO.sol b/contracts/protocol/Sector3DAO.sol index 7d70eb7..f0ec4b1 100644 --- a/contracts/protocol/Sector3DAO.sol +++ b/contracts/protocol/Sector3DAO.sol @@ -70,9 +70,9 @@ contract Sector3DAO { token = token_; } - function deployPriority(string calldata title, address rewardToken, uint16 epochDurationInDays, uint256 epochBudget) public returns (Sector3DAOPriority) { + function deployPriority(string calldata title, address rewardToken, uint16 epochDurationInDays, uint256 epochBudget, address gatingNFT) public returns (Sector3DAOPriority) { require(msg.sender == owner, "You aren't the owner"); - Sector3DAOPriority priority = new Sector3DAOPriority(address(this), title, rewardToken, epochDurationInDays, epochBudget); + Sector3DAOPriority priority = new Sector3DAOPriority(address(this), title, rewardToken, epochDurationInDays, epochBudget, gatingNFT); priorities.push(priority); return priority; } diff --git a/contracts/protocol/Sector3DAOPriority.sol b/contracts/protocol/Sector3DAOPriority.sol index 4f03983..e94c08d 100644 --- a/contracts/protocol/Sector3DAOPriority.sol +++ b/contracts/protocol/Sector3DAOPriority.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.17; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; import "./IPriority.sol"; import "./Enums.sol"; import "./Structs.sol"; @@ -15,6 +16,7 @@ contract Sector3DAOPriority is IPriority { uint256 public immutable startTime; uint16 public immutable epochDuration; uint256 public immutable epochBudget; + IERC721 public immutable gatingNFT; Contribution[] contributions; event ContributionAdded(Contribution contribution); @@ -22,14 +24,16 @@ contract Sector3DAOPriority is IPriority { error EpochNotYetEnded(); error NoRewardForEpoch(); + error NoGatingNFTOwnership(); - constructor(address dao_, string memory title_, address rewardToken_, uint16 epochDurationInDays, uint256 epochBudget_) { + constructor(address dao_, string memory title_, address rewardToken_, uint16 epochDurationInDays, uint256 epochBudget_, address gatingNFT_) { dao = dao_; title = title_; rewardToken = IERC20(rewardToken_); startTime = block.timestamp; epochDuration = epochDurationInDays; epochBudget = epochBudget_; + gatingNFT = IERC721(gatingNFT_); } /** @@ -51,6 +55,11 @@ contract Sector3DAOPriority is IPriority { } function addContribution2(string memory description, string memory proofURL, uint8 hoursSpent, Alignment alignment) public { + if (address(gatingNFT) != address(0x0)) { + if (gatingNFT.balanceOf(msg.sender) == 0) { + revert NoGatingNFTOwnership(); + } + } Contribution memory contribution = Contribution({ timestamp: block.timestamp, epochIndex: getEpochIndex(), diff --git a/contracts/token/Sector3Dove.sol b/contracts/token/Sector3Dove.sol new file mode 100644 index 0000000..c06e616 --- /dev/null +++ b/contracts/token/Sector3Dove.sol @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + +import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; +import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; +import "@openzeppelin/contracts/utils/Counters.sol"; + +contract Sector3Dove is ERC721, ERC721Enumerable, Ownable { + using Counters for Counters.Counter; + + Counters.Counter private _tokenIdCounter; + + constructor() ERC721(unicode"Sector#3 Dove 🕊️", "S3DOVE") {} + + function safeMint(address to) public onlyOwner { + uint256 tokenId = _tokenIdCounter.current(); + _tokenIdCounter.increment(); + _safeMint(to, tokenId); + } + + // The following functions are overrides required by Solidity. + + function _beforeTokenTransfer(address from, address to, uint256 tokenId, uint256 batchSize) + internal + override(ERC721, ERC721Enumerable) + { + super._beforeTokenTransfer(from, to, tokenId, batchSize); + } + + function supportsInterface(bytes4 interfaceId) + public + view + override(ERC721, ERC721Enumerable) + returns (bool) + { + return super.supportsInterface(interfaceId); + } +} diff --git a/scripts/deploy-nft.ts b/scripts/deploy-nft.ts new file mode 100644 index 0000000..3e1afe1 --- /dev/null +++ b/scripts/deploy-nft.ts @@ -0,0 +1,22 @@ +import { ethers } from "hardhat"; + +async function main() { + console.log('Deploying token/Sector3Dove.sol') + + console.log('process.env.DEPLOYER_PRIVATE_KEY exists:', process.env.DEPLOYER_PRIVATE_KEY != undefined) + console.log('process.env.ETHERSCAN_API_KEY exists:', process.env.ETHERSCAN_API_KEY != undefined) + + const Sector3Dove = await ethers.getContractFactory("Sector3Dove"); + const sector3Dove = await Sector3Dove.deploy(); + + await sector3Dove.deployed(); + + console.log(`Sector3Dove deployed to ${sector3Dove.address}`); +} + +// We recommend this pattern to be able to use async/await everywhere +// and properly handle errors. +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/test/Sector3DAO.ts b/test/Sector3DAO.ts index efcd124..dc43649 100644 --- a/test/Sector3DAO.ts +++ b/test/Sector3DAO.ts @@ -59,12 +59,12 @@ describe("Sector3DAO", function () { console.log('priorities:', priorities); expect(priorities.length).to.equal(0); - await sector3DAO.deployPriority('Priority #1', '0x942d6e75465C3c248Eb8775472c853d2b56139fE', 7, (2.049 * 1e18).toString()); + await sector3DAO.deployPriority('Priority #1', '0x942d6e75465C3c248Eb8775472c853d2b56139fE', 7, (2.049 * 1e18).toString(), ethers.constants.AddressZero); priorities = await sector3DAO.getPriorities(); console.log('priorities:', priorities); expect(priorities.length).to.equal(1); - await sector3DAO.deployPriority('Priority #2', '0x942d6e75465C3c248Eb8775472c853d2b56139fE', 14, (4.098 * 1e18).toString()); + await sector3DAO.deployPriority('Priority #2', '0x942d6e75465C3c248Eb8775472c853d2b56139fE', 14, (4.098 * 1e18).toString(), ethers.constants.AddressZero); priorities = await sector3DAO.getPriorities(); console.log('priorities:', priorities); expect(priorities.length).to.equal(2); @@ -73,7 +73,7 @@ describe("Sector3DAO", function () { it("remove priority - from array of 1", async function () { const { sector3DAO } = await loadFixture(deployOneYearLockFixture); - await sector3DAO.deployPriority('Priority #1', '0x942d6e75465C3c248Eb8775472c853d2b56139fE', 7, (2.049 * 1e18).toString()); + await sector3DAO.deployPriority('Priority #1', '0x942d6e75465C3c248Eb8775472c853d2b56139fE', 7, (2.049 * 1e18).toString(), ethers.constants.AddressZero); let priorities = await sector3DAO.getPriorities(); console.log('priorities:', priorities); expect(priorities.length).to.equal(1); @@ -87,8 +87,8 @@ describe("Sector3DAO", function () { it("remove priority - from array of 2", async function () { const { sector3DAO } = await loadFixture(deployOneYearLockFixture); - await sector3DAO.deployPriority('Priority #1', '0x942d6e75465C3c248Eb8775472c853d2b56139fE', 7, (2.049 * 1e18).toString()); - await sector3DAO.deployPriority('Priority #2', '0x942d6e75465C3c248Eb8775472c853d2b56139fE', 14, (4.098 * 1e18).toString()); + await sector3DAO.deployPriority('Priority #1', '0x942d6e75465C3c248Eb8775472c853d2b56139fE', 7, (2.049 * 1e18).toString(), ethers.constants.AddressZero); + await sector3DAO.deployPriority('Priority #2', '0x942d6e75465C3c248Eb8775472c853d2b56139fE', 14, (4.098 * 1e18).toString(), ethers.constants.AddressZero); let priorities = await sector3DAO.getPriorities(); console.log('priorities:', priorities); expect(priorities.length).to.equal(2); @@ -103,8 +103,8 @@ describe("Sector3DAO", function () { it("remove priority, then deploy priority", async function () { const { sector3DAO } = await loadFixture(deployOneYearLockFixture); - await sector3DAO.deployPriority('Priority #1', '0x942d6e75465C3c248Eb8775472c853d2b56139fE', 7, (2.049 * 1e18).toString()); - await sector3DAO.deployPriority('Priority #2', '0x942d6e75465C3c248Eb8775472c853d2b56139fE', 14, (4.098 * 1e18).toString()); + await sector3DAO.deployPriority('Priority #1', '0x942d6e75465C3c248Eb8775472c853d2b56139fE', 7, (2.049 * 1e18).toString(), ethers.constants.AddressZero); + await sector3DAO.deployPriority('Priority #2', '0x942d6e75465C3c248Eb8775472c853d2b56139fE', 14, (4.098 * 1e18).toString(), ethers.constants.AddressZero); let priorities = await sector3DAO.getPriorities(); console.log('priorities:', priorities); expect(priorities.length).to.equal(2); @@ -115,7 +115,7 @@ describe("Sector3DAO", function () { expect(prioritiesAfterRemoval.length).to.equal(1); expect(prioritiesAfterRemoval[0]).to.equal(priorities[1]); - await sector3DAO.deployPriority('Priority #3', '0x942d6e75465C3c248Eb8775472c853d2b56139fE', 21, (6.147 * 1e18).toString()); + await sector3DAO.deployPriority('Priority #3', '0x942d6e75465C3c248Eb8775472c853d2b56139fE', 21, (6.147 * 1e18).toString(), ethers.constants.AddressZero); priorities = await sector3DAO.getPriorities(); console.log('priorities:', priorities); expect(priorities.length).to.equal(2); diff --git a/test/Sector3Priority.ts b/test/Sector3Priority.ts index 629c984..d75b1cc 100644 --- a/test/Sector3Priority.ts +++ b/test/Sector3Priority.ts @@ -21,7 +21,8 @@ describe("Sector3DAOPriority", function () { const rewardToken = await SECTOR3.deploy(); const epochDurationInDays = 7; // Weekly const epochBudget = (2.049 * 1e18).toString(); // 2.049 - const sector3DAOPriority = await Sector3DAOPriority.deploy(dao, title, rewardToken.address, epochDurationInDays, epochBudget); + const gatingNFT = ethers.constants.AddressZero; + const sector3DAOPriority = await Sector3DAOPriority.deploy(dao, title, rewardToken.address, epochDurationInDays, epochBudget, gatingNFT); return { sector3DAOPriority, owner, otherAccount, rewardToken }; } @@ -42,7 +43,8 @@ describe("Sector3DAOPriority", function () { const rewardToken = await SECTOR3.deploy(); const epochDurationInDays = 14; // Biweekly const epochBudget = (2.049 * 1e18).toString(); // 2.049 - const sector3DAOPriority = await Sector3DAOPriority.deploy(dao, title, rewardToken.address, epochDurationInDays, epochBudget); + const gatingNFT = ethers.constants.AddressZero; + const sector3DAOPriority = await Sector3DAOPriority.deploy(dao, title, rewardToken.address, epochDurationInDays, epochBudget, gatingNFT); return { sector3DAOPriority, owner, otherAccount, rewardToken }; } @@ -63,11 +65,38 @@ describe("Sector3DAOPriority", function () { const rewardToken = await SECTOR3.deploy(); const epochDurationInDays = 28; // Monthly const epochBudget = (2.049 * 1e18).toString(); // 2.049 - const sector3DAOPriority = await Sector3DAOPriority.deploy(dao, title, rewardToken.address, epochDurationInDays, epochBudget); + const gatingNFT = ethers.constants.AddressZero; + const sector3DAOPriority = await Sector3DAOPriority.deploy(dao, title, rewardToken.address, epochDurationInDays, epochBudget, gatingNFT); return { sector3DAOPriority, owner, otherAccount, rewardToken }; } + + // We define a fixture to reuse the same setup in every test. + // We use loadFixture to run this setup once, snapshot that state, + // and reset Hardhat Network to that snapshot in every test. + async function deployWeeklyFixtureWithNFTGating() { + console.log('deployWeeklyFixtureWithNFTGating') + + // Contracts are deployed using the first signer/account by default + const [owner, otherAccount] = await ethers.getSigners(); + console.log('owner.address:', owner.address); + console.log('otherAccount.address:', otherAccount.address); + + const Sector3DAOPriority = await ethers.getContractFactory("Sector3DAOPriority"); + const dao = "0x96Bf89193E2A07720e42bA3AD736128a45537e63"; // Sector#3 + const title = "Priority Title"; + const SECTOR3 = await ethers.getContractFactory("SECTOR3"); + const rewardToken = await SECTOR3.deploy(); + const epochDurationInDays = 7; // Weekly + const epochBudget = (2.049 * 1e18).toString(); // 2.049 + const Sector3Dove = await ethers.getContractFactory("Sector3Dove"); + const gatingNFT = await Sector3Dove.deploy(); + const sector3DAOPriority = await Sector3DAOPriority.deploy(dao, title, rewardToken.address, epochDurationInDays, epochBudget, gatingNFT.address); + + return { sector3DAOPriority, owner, otherAccount, rewardToken, gatingNFT }; + } + describe("Deployment", function() { it("Should set the right DAO address", async function() { @@ -413,6 +442,37 @@ describe("Sector3DAOPriority", function () { }); }); + + describe("NFT gating - addContribution2", async function() { + it("should fail if NFT gating", async function() { + const { sector3DAOPriority, owner } = await loadFixture(deployWeeklyFixtureWithNFTGating); + + await expect(sector3DAOPriority.addContribution2( + "Description (test)", + "https://github.com/sector-3", + 10, + 3 // Alignment.Mostly + )).to.be.revertedWithCustomError( + sector3DAOPriority, + "NoGatingNFTOwnership" + ) + }); + + it("should succeed if NFT gating and account is NFT owner", async function() { + const { sector3DAOPriority, owner, gatingNFT } = await loadFixture(deployWeeklyFixtureWithNFTGating); + + await gatingNFT.safeMint(owner.address); + + await sector3DAOPriority.addContribution2( + "Description (test)", + "https://github.com/sector-3", + 10, + 3 // Alignment.Mostly + ); + expect(await sector3DAOPriority.getContributionCount()).to.equal(1); + }); + }); + describe("getAllocationPercentage", async function() { it("Should be 100% if one contributor", async function() { From 97ddf374e997bd271fb07611aa3cbe415facb795 Mon Sep 17 00:00:00 2001 From: aahna-ashina <95955389+aahna-ashina@users.noreply.github.com> Date: Sun, 12 Mar 2023 14:51:56 +0800 Subject: [PATCH 02/17] chore: v0.5.0 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5d79126..34d9232 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "section3-contracts", - "version": "0.2.0", + "version": "0.5.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "section3-contracts", - "version": "0.2.0", + "version": "0.5.0", "license": "MIT", "devDependencies": { "@nomicfoundation/hardhat-toolbox": "^2.0.0", diff --git a/package.json b/package.json index 735f6c2..4dff317 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "section3-contracts", - "version": "0.2.0", + "version": "0.5.0", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, From fe0fead0deb0b00f22b94e687afd56c104fdc24e Mon Sep 17 00:00:00 2001 From: aahna-ashina <95955389+aahna-ashina@users.noreply.github.com> Date: Sun, 12 Mar 2023 14:57:04 +0800 Subject: [PATCH 03/17] chore: prepare for v1 --- contracts/protocol/Sector3DAO.sol | 2 +- package-lock.json | 4 ++-- package.json | 2 +- test/Sector3DAO.ts | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/contracts/protocol/Sector3DAO.sol b/contracts/protocol/Sector3DAO.sol index f0ec4b1..ee6c826 100644 --- a/contracts/protocol/Sector3DAO.sol +++ b/contracts/protocol/Sector3DAO.sol @@ -12,7 +12,7 @@ contract Sector3DAO { /** * The protocol version. */ - uint8 public constant version = 0; + uint8 public constant version = 1; /** * The smart contract owner. diff --git a/package-lock.json b/package-lock.json index 34d9232..9cff962 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "section3-contracts", - "version": "0.5.0", + "version": "1.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "section3-contracts", - "version": "0.5.0", + "version": "1.0.0", "license": "MIT", "devDependencies": { "@nomicfoundation/hardhat-toolbox": "^2.0.0", diff --git a/package.json b/package.json index 4dff317..a1cb826 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "section3-contracts", - "version": "0.5.0", + "version": "1.0.0", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, diff --git a/test/Sector3DAO.ts b/test/Sector3DAO.ts index dc43649..52c7c75 100644 --- a/test/Sector3DAO.ts +++ b/test/Sector3DAO.ts @@ -23,7 +23,7 @@ describe("Sector3DAO", function () { it("Should set the right version", async function () { const { sector3DAO } = await loadFixture(deployOneYearLockFixture); - expect(await sector3DAO.version()).to.equal(0); + expect(await sector3DAO.version()).to.equal(1); }); it("Should set the right owner", async function () { From aab5f16d43cf204800ea999e6d5a539d356faa6e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 12 Mar 2023 07:11:37 +0000 Subject: [PATCH 04/17] chore(deps-dev): bump @openzeppelin/contracts from 4.8.1 to 4.8.2 Bumps [@openzeppelin/contracts](https://github.com/OpenZeppelin/openzeppelin-contracts) from 4.8.1 to 4.8.2. - [Release notes](https://github.com/OpenZeppelin/openzeppelin-contracts/releases) - [Changelog](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/CHANGELOG.md) - [Commits](https://github.com/OpenZeppelin/openzeppelin-contracts/compare/v4.8.1...v4.8.2) --- updated-dependencies: - dependency-name: "@openzeppelin/contracts" dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9cff962..8d11126 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "devDependencies": { "@nomicfoundation/hardhat-toolbox": "^2.0.0", "@nomiclabs/hardhat-etherscan": "^3.1.4", - "@openzeppelin/contracts": "^4.8.1", + "@openzeppelin/contracts": "^4.8.2", "dotenv": "^16.0.3", "hardhat": "^2.12.7" } @@ -1576,9 +1576,9 @@ } }, "node_modules/@openzeppelin/contracts": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.8.1.tgz", - "integrity": "sha512-xQ6eUZl+RDyb/FiZe1h+U7qr/f4p/SrTSQcTPH2bjur3C5DbuW/zFgCU/b1P/xcIaEqJep+9ju4xDRi3rmChdQ==", + "version": "4.8.2", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.8.2.tgz", + "integrity": "sha512-kEUOgPQszC0fSYWpbh2kT94ltOJwj1qfT2DWo+zVttmGmf97JZ99LspePNaeeaLhCImaHVeBbjaQFZQn7+Zc5g==", "dev": true }, "node_modules/@scure/base": { @@ -10174,9 +10174,9 @@ } }, "@openzeppelin/contracts": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.8.1.tgz", - "integrity": "sha512-xQ6eUZl+RDyb/FiZe1h+U7qr/f4p/SrTSQcTPH2bjur3C5DbuW/zFgCU/b1P/xcIaEqJep+9ju4xDRi3rmChdQ==", + "version": "4.8.2", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.8.2.tgz", + "integrity": "sha512-kEUOgPQszC0fSYWpbh2kT94ltOJwj1qfT2DWo+zVttmGmf97JZ99LspePNaeeaLhCImaHVeBbjaQFZQn7+Zc5g==", "dev": true }, "@scure/base": { diff --git a/package.json b/package.json index a1cb826..a6a9477 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "devDependencies": { "@nomicfoundation/hardhat-toolbox": "^2.0.0", "@nomiclabs/hardhat-etherscan": "^3.1.4", - "@openzeppelin/contracts": "^4.8.1", + "@openzeppelin/contracts": "^4.8.2", "dotenv": "^16.0.3", "hardhat": "^2.12.7" } From 1eda2e14faabf08751819ee32bef435ad4446fa0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 12 Mar 2023 07:13:08 +0000 Subject: [PATCH 05/17] chore(deps-dev): bump @nomicfoundation/hardhat-toolbox Bumps [@nomicfoundation/hardhat-toolbox](https://github.com/nomicfoundation/hardhat) from 2.0.0 to 2.0.2. - [Release notes](https://github.com/nomicfoundation/hardhat/releases) - [Commits](https://github.com/nomicfoundation/hardhat/compare/@nomicfoundation/hardhat-toolbox@2.0.0...@nomicfoundation/hardhat-toolbox@2.0.2) --- updated-dependencies: - dependency-name: "@nomicfoundation/hardhat-toolbox" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package-lock.json | 16 ++++++++-------- package.json | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9cff962..b06730b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "1.0.0", "license": "MIT", "devDependencies": { - "@nomicfoundation/hardhat-toolbox": "^2.0.0", + "@nomicfoundation/hardhat-toolbox": "^2.0.2", "@nomiclabs/hardhat-etherscan": "^3.1.4", "@openzeppelin/contracts": "^4.8.1", "dotenv": "^16.0.3", @@ -1336,9 +1336,9 @@ } }, "node_modules/@nomicfoundation/hardhat-toolbox": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-toolbox/-/hardhat-toolbox-2.0.0.tgz", - "integrity": "sha512-BoOPbzLQ1GArnBZd4Jz4IU8FY3RY4nUwpXlfymXwxlXNimngkPRJj7ivVNurD7igohEjf90v/Axn2M5WwAdCJQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-toolbox/-/hardhat-toolbox-2.0.2.tgz", + "integrity": "sha512-vnN1AzxbvpSx9pfdRHbUzTRIXpMLPXnUlkW855VaDk6N1pwRaQ2gNzEmFAABk4lWf11E00PKwFd/q27HuwYrYg==", "dev": true, "peerDependencies": { "@ethersproject/abi": "^5.4.7", @@ -1350,7 +1350,7 @@ "@typechain/ethers-v5": "^10.1.0", "@typechain/hardhat": "^6.1.2", "@types/chai": "^4.2.0", - "@types/mocha": "^9.1.0", + "@types/mocha": ">=9.1.0", "@types/node": ">=12.0.0", "chai": "^4.2.0", "ethers": "^5.4.7", @@ -10053,9 +10053,9 @@ } }, "@nomicfoundation/hardhat-toolbox": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-toolbox/-/hardhat-toolbox-2.0.0.tgz", - "integrity": "sha512-BoOPbzLQ1GArnBZd4Jz4IU8FY3RY4nUwpXlfymXwxlXNimngkPRJj7ivVNurD7igohEjf90v/Axn2M5WwAdCJQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-toolbox/-/hardhat-toolbox-2.0.2.tgz", + "integrity": "sha512-vnN1AzxbvpSx9pfdRHbUzTRIXpMLPXnUlkW855VaDk6N1pwRaQ2gNzEmFAABk4lWf11E00PKwFd/q27HuwYrYg==", "dev": true, "requires": {} }, diff --git a/package.json b/package.json index a1cb826..6902b29 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ }, "license": "MIT", "devDependencies": { - "@nomicfoundation/hardhat-toolbox": "^2.0.0", + "@nomicfoundation/hardhat-toolbox": "^2.0.2", "@nomiclabs/hardhat-etherscan": "^3.1.4", "@openzeppelin/contracts": "^4.8.1", "dotenv": "^16.0.3", From f403c43d6716afe4fd5b0301729ac1adde17357c Mon Sep 17 00:00:00 2001 From: aahna-ashina <95955389+aahna-ashina@users.noreply.github.com> Date: Sun, 12 Mar 2023 16:31:48 +0800 Subject: [PATCH 06/17] refactor: remove obsolete code --- contracts/protocol/Enums.sol | 4 - contracts/protocol/IPriority.sol | 5 +- contracts/protocol/Sector3DAO.sol | 4 - contracts/protocol/Sector3DAOFactory.sol | 9 +- contracts/protocol/Sector3DAOPriority.sol | 23 +- contracts/protocol/Structs.sol | 5 +- test/Sector3DAO.ts | 42 +- test/Sector3DAOFactory.ts | 87 ++++ test/Sector3Priority.ts | 482 ++++++++++------------ 9 files changed, 325 insertions(+), 336 deletions(-) delete mode 100644 contracts/protocol/Enums.sol create mode 100644 test/Sector3DAOFactory.ts diff --git a/contracts/protocol/Enums.sol b/contracts/protocol/Enums.sol deleted file mode 100644 index 09f6b19..0000000 --- a/contracts/protocol/Enums.sol +++ /dev/null @@ -1,4 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.17; - -enum Alignment { None, Barely, Moderately, Mostly, Highly, Perfectly } diff --git a/contracts/protocol/IPriority.sol b/contracts/protocol/IPriority.sol index c6c003b..46e3ba0 100644 --- a/contracts/protocol/IPriority.sol +++ b/contracts/protocol/IPriority.sol @@ -1,15 +1,12 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.17; -import "./Enums.sol"; -import "./Structs.sol"; - interface IPriority { /** * Add a contribution for the current epoch. */ - function addContribution(Contribution memory contribution) external; + function addContribution(string memory description, string memory proofURL, uint8 hoursSpent, uint8 alignmentPercentage) external; /** * Claim reward for contributions made in a past epoch. diff --git a/contracts/protocol/Sector3DAO.sol b/contracts/protocol/Sector3DAO.sol index ee6c826..27f1c65 100644 --- a/contracts/protocol/Sector3DAO.sol +++ b/contracts/protocol/Sector3DAO.sol @@ -77,10 +77,6 @@ contract Sector3DAO { return priority; } - function getPriorityCount() public view returns (uint16) { - return uint16(priorities.length); - } - function getPriorities() public view returns (Sector3DAOPriority[] memory) { return priorities; } diff --git a/contracts/protocol/Sector3DAOFactory.sol b/contracts/protocol/Sector3DAOFactory.sol index 9aa4c06..de3426c 100644 --- a/contracts/protocol/Sector3DAOFactory.sol +++ b/contracts/protocol/Sector3DAOFactory.sol @@ -11,11 +11,10 @@ contract Sector3DAOFactory { constructor() { owner = msg.sender; - // daos.push(0x5FbDB2315678afecb367f032d93F642f64180aa3); // localhost - daos.push(0xEa98D59e4EF83822393AF87e587713c2674eD4FD); // Sector#3 DAO (v0) - daos.push(0xd87246302AE8f12485BB525f27778106c636166e); // BanklessDAO (v3) - daos.push(0x2D624a0bA38b40B4f7bE2bfeb56B6B0dD81Be6A1); // Nation3 (v0) - daos.push(0x9741B82017485759c9Bcc13FeA10c1105f82d25C); // Bankless Africa (v0) + // // daos.push(0x5FbDB2315678afecb367f032d93F642f64180aa3); // localhost + // daos.push(0xEa98D59e4EF83822393AF87e587713c2674eD4FD); // Sector#3 DAO (v0) + // daos.push(0x2D624a0bA38b40B4f7bE2bfeb56B6B0dD81Be6A1); // Nation3 (v0) + // daos.push(0x9741B82017485759c9Bcc13FeA10c1105f82d25C); // Bankless Africa (v0) } function setOwner(address owner_) public { diff --git a/contracts/protocol/Sector3DAOPriority.sol b/contracts/protocol/Sector3DAOPriority.sol index e94c08d..29fa822 100644 --- a/contracts/protocol/Sector3DAOPriority.sol +++ b/contracts/protocol/Sector3DAOPriority.sol @@ -4,7 +4,6 @@ pragma solidity ^0.8.17; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; import "./IPriority.sol"; -import "./Enums.sol"; import "./Structs.sol"; contract Sector3DAOPriority is IPriority { @@ -45,16 +44,7 @@ contract Sector3DAOPriority is IPriority { return uint16(timePassedSinceStart / epochDurationInSeconds); } - function addContribution(Contribution memory contribution) public { - contribution.timestamp = block.timestamp; - contribution.epochIndex = getEpochIndex(); - contribution.contributor = msg.sender; - contribution.alignmentPercentage = uint8(contribution.alignment) * 20; - contributions.push(contribution); - emit ContributionAdded(contribution); - } - - function addContribution2(string memory description, string memory proofURL, uint8 hoursSpent, Alignment alignment) public { + function addContribution(string memory description, string memory proofURL, uint8 hoursSpent, uint8 alignmentPercentage) public { if (address(gatingNFT) != address(0x0)) { if (gatingNFT.balanceOf(msg.sender) == 0) { revert NoGatingNFTOwnership(); @@ -67,25 +57,16 @@ contract Sector3DAOPriority is IPriority { description: description, proofURL: proofURL, hoursSpent: hoursSpent, - alignment: alignment, - alignmentPercentage: uint8(alignment) * 20 + alignmentPercentage: alignmentPercentage }); contributions.push(contribution); emit ContributionAdded(contribution); } - function getContributionCount() public view returns (uint16) { - return uint16(contributions.length); - } - function getContributions() public view returns (Contribution[] memory) { return contributions; } - function getContribution(uint16 index) public view returns (Contribution memory) { - return contributions[index]; - } - /** * Claims a contributor's reward for contributions made in a given epoch. * diff --git a/contracts/protocol/Structs.sol b/contracts/protocol/Structs.sol index 8ae77b3..b507cee 100644 --- a/contracts/protocol/Structs.sol +++ b/contracts/protocol/Structs.sol @@ -1,15 +1,12 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.17; -import "./Enums.sol"; - struct Contribution { uint256 timestamp; uint16 epochIndex; address contributor; string description; string proofURL; - Alignment alignment; - uint8 alignmentPercentage; uint8 hoursSpent; + uint8 alignmentPercentage; } diff --git a/test/Sector3DAO.ts b/test/Sector3DAO.ts index 52c7c75..4c49dc4 100644 --- a/test/Sector3DAO.ts +++ b/test/Sector3DAO.ts @@ -7,8 +7,8 @@ describe("Sector3DAO", function () { // We define a fixture to reuse the same setup in every test. // We use loadFixture to run this setup once, snapshot that state, // and reset Hardhat Network to that snapshot in every test. - async function deployOneYearLockFixture() { - console.log('deployOneYearLockFixture') + async function deployFixture() { + console.log('deployFixture') // Contracts are deployed using the first signer/account by default const [owner, otherAccount] = await ethers.getSigners(); @@ -21,31 +21,31 @@ describe("Sector3DAO", function () { describe("Deployment", function () { it("Should set the right version", async function () { - const { sector3DAO } = await loadFixture(deployOneYearLockFixture); + const { sector3DAO } = await loadFixture(deployFixture); expect(await sector3DAO.version()).to.equal(1); }); it("Should set the right owner", async function () { - const { sector3DAO, owner } = await loadFixture(deployOneYearLockFixture); + const { sector3DAO, owner } = await loadFixture(deployFixture); expect(await sector3DAO.owner()).to.equal(owner.address); }); it("Should set the right DAO name", async function () { - const { sector3DAO } = await loadFixture(deployOneYearLockFixture); + const { sector3DAO } = await loadFixture(deployFixture); expect(await sector3DAO.name()).to.equal("Name Value"); }); it("Should set the right DAO purpose", async function () { - const { sector3DAO } = await loadFixture(deployOneYearLockFixture); + const { sector3DAO } = await loadFixture(deployFixture); expect(await sector3DAO.purpose()).to.equal("Purpose Value"); }); it("Should set the right DAO token", async function () { - const { sector3DAO } = await loadFixture(deployOneYearLockFixture); + const { sector3DAO } = await loadFixture(deployFixture); expect(await sector3DAO.token()).to.equal("0x942d6e75465C3c248Eb8775472c853d2b56139fE"); }); @@ -53,71 +53,71 @@ describe("Sector3DAO", function () { describe("Priorities", function () { it("deploy priority", async function () { - const { sector3DAO } = await loadFixture(deployOneYearLockFixture); + const { sector3DAO } = await loadFixture(deployFixture); let priorities = await sector3DAO.getPriorities(); - console.log('priorities:', priorities); + // console.log('priorities:', priorities); expect(priorities.length).to.equal(0); await sector3DAO.deployPriority('Priority #1', '0x942d6e75465C3c248Eb8775472c853d2b56139fE', 7, (2.049 * 1e18).toString(), ethers.constants.AddressZero); priorities = await sector3DAO.getPriorities(); - console.log('priorities:', priorities); + // console.log('priorities:', priorities); expect(priorities.length).to.equal(1); await sector3DAO.deployPriority('Priority #2', '0x942d6e75465C3c248Eb8775472c853d2b56139fE', 14, (4.098 * 1e18).toString(), ethers.constants.AddressZero); priorities = await sector3DAO.getPriorities(); - console.log('priorities:', priorities); + // console.log('priorities:', priorities); expect(priorities.length).to.equal(2); }) it("remove priority - from array of 1", async function () { - const { sector3DAO } = await loadFixture(deployOneYearLockFixture); + const { sector3DAO } = await loadFixture(deployFixture); await sector3DAO.deployPriority('Priority #1', '0x942d6e75465C3c248Eb8775472c853d2b56139fE', 7, (2.049 * 1e18).toString(), ethers.constants.AddressZero); let priorities = await sector3DAO.getPriorities(); - console.log('priorities:', priorities); + // console.log('priorities:', priorities); expect(priorities.length).to.equal(1); await sector3DAO.removePriority(priorities[0]); const prioritiesAfterRemoval = await sector3DAO.getPriorities(); - console.log('prioritiesAfterRemoval:', prioritiesAfterRemoval); + // console.log('prioritiesAfterRemoval:', prioritiesAfterRemoval); expect(prioritiesAfterRemoval.length).to.equal(0); }) it("remove priority - from array of 2", async function () { - const { sector3DAO } = await loadFixture(deployOneYearLockFixture); + const { sector3DAO } = await loadFixture(deployFixture); await sector3DAO.deployPriority('Priority #1', '0x942d6e75465C3c248Eb8775472c853d2b56139fE', 7, (2.049 * 1e18).toString(), ethers.constants.AddressZero); await sector3DAO.deployPriority('Priority #2', '0x942d6e75465C3c248Eb8775472c853d2b56139fE', 14, (4.098 * 1e18).toString(), ethers.constants.AddressZero); let priorities = await sector3DAO.getPriorities(); - console.log('priorities:', priorities); + // console.log('priorities:', priorities); expect(priorities.length).to.equal(2); await sector3DAO.removePriority(priorities[0]); const prioritiesAfterRemoval = await sector3DAO.getPriorities(); - console.log('prioritiesAfterRemoval:', prioritiesAfterRemoval); + // console.log('prioritiesAfterRemoval:', prioritiesAfterRemoval); expect(prioritiesAfterRemoval.length).to.equal(1); expect(prioritiesAfterRemoval[0]).to.equal(priorities[1]); }) it("remove priority, then deploy priority", async function () { - const { sector3DAO } = await loadFixture(deployOneYearLockFixture); + const { sector3DAO } = await loadFixture(deployFixture); await sector3DAO.deployPriority('Priority #1', '0x942d6e75465C3c248Eb8775472c853d2b56139fE', 7, (2.049 * 1e18).toString(), ethers.constants.AddressZero); await sector3DAO.deployPriority('Priority #2', '0x942d6e75465C3c248Eb8775472c853d2b56139fE', 14, (4.098 * 1e18).toString(), ethers.constants.AddressZero); let priorities = await sector3DAO.getPriorities(); - console.log('priorities:', priorities); + // console.log('priorities:', priorities); expect(priorities.length).to.equal(2); await sector3DAO.removePriority(priorities[0]); const prioritiesAfterRemoval = await sector3DAO.getPriorities(); - console.log('prioritiesAfterRemoval:', prioritiesAfterRemoval); + // console.log('prioritiesAfterRemoval:', prioritiesAfterRemoval); expect(prioritiesAfterRemoval.length).to.equal(1); expect(prioritiesAfterRemoval[0]).to.equal(priorities[1]); await sector3DAO.deployPriority('Priority #3', '0x942d6e75465C3c248Eb8775472c853d2b56139fE', 21, (6.147 * 1e18).toString(), ethers.constants.AddressZero); priorities = await sector3DAO.getPriorities(); - console.log('priorities:', priorities); + // console.log('priorities:', priorities); expect(priorities.length).to.equal(2); }) }) diff --git a/test/Sector3DAOFactory.ts b/test/Sector3DAOFactory.ts new file mode 100644 index 0000000..5898461 --- /dev/null +++ b/test/Sector3DAOFactory.ts @@ -0,0 +1,87 @@ +import { time, loadFixture } from "@nomicfoundation/hardhat-network-helpers"; +import { anyValue } from "@nomicfoundation/hardhat-chai-matchers/withArgs"; +import { expect } from "chai"; +import { ethers } from "hardhat"; + +describe("Sector3DAOFactory", function () { + // We define a fixture to reuse the same setup in every test. + // We use loadFixture to run this setup once, snapshot that state, + // and reset Hardhat Network to that snapshot in every test. + async function deployFixture() { + console.log('deployFixture') + + // Contracts are deployed using the first signer/account by default + const [owner, otherAccount] = await ethers.getSigners(); + + const Sector3DAOFactory = await ethers.getContractFactory("Sector3DAOFactory"); + const sector3DAOFactory = await Sector3DAOFactory.deploy(); + + return { sector3DAOFactory, owner, otherAccount }; + } + + describe("Deployment", function () { + it("Should set the right owner", async function () { + const { sector3DAOFactory, owner } = await loadFixture(deployFixture); + + expect(await sector3DAOFactory.owner()).to.equal(owner.address); + }); + }); + + describe("DAOs", function () { + it("deploy DAO", async function () { + const { sector3DAOFactory } = await loadFixture(deployFixture); + + let daos = await sector3DAOFactory.getDAOs(); + // console.log('daos:', daos); + expect(daos.length).to.equal(0); + + await sector3DAOFactory.deployDAO("DAO #1", "Purpose #1", "0x610210AA5D51bf26CBce146A5992D2FEeBc27dB1"); + daos = await sector3DAOFactory.getDAOs(); + // console.log('daos:', daos); + expect(daos.length).to.equal(1); + + await sector3DAOFactory.deployDAO("DAO #2", "Purpose #2", "0x610210AA5D51bf26CBce146A5992D2FEeBc27dB1"); + daos = await sector3DAOFactory.getDAOs(); + // console.log('daos:', daos); + expect(daos.length).to.equal(2); + }) + }) + + it("remove DAO - from array of 1", async function () { + const { sector3DAOFactory } = await loadFixture(deployFixture); + + let daos = await sector3DAOFactory.getDAOs(); + // console.log('daos:', daos); + expect(daos.length).to.equal(0); + + await sector3DAOFactory.deployDAO("DAO #1", "Purpose #1", "0x610210AA5D51bf26CBce146A5992D2FEeBc27dB1"); + await sector3DAOFactory.deployDAO("DAO #2", "Purpose #2", "0x610210AA5D51bf26CBce146A5992D2FEeBc27dB1"); + daos = await sector3DAOFactory.getDAOs(); + // console.log('daos:', daos); + expect(daos.length).to.equal(2); + + await sector3DAOFactory.removeDAO(daos[0]); + const daosAfterRemoval = await sector3DAOFactory.getDAOs(); + console.log('daosAfterRemoval:', daosAfterRemoval); + expect(daosAfterRemoval.length).to.equal(1); + expect(daosAfterRemoval[0]).to.equal(daos[1]); + }) + + it("remove DAO - from array of 2", async function () { + const { sector3DAOFactory } = await loadFixture(deployFixture); + + let daos = await sector3DAOFactory.getDAOs(); + // console.log('daos:', daos); + expect(daos.length).to.equal(0); + + await sector3DAOFactory.deployDAO("DAO #1", "Purpose #1", "0x610210AA5D51bf26CBce146A5992D2FEeBc27dB1"); + daos = await sector3DAOFactory.getDAOs(); + // console.log('daos:', daos); + expect(daos.length).to.equal(1); + + await sector3DAOFactory.removeDAO(daos[0]); + const daosAfterRemoval = await sector3DAOFactory.getDAOs(); + console.log('daosAfterRemoval:', daosAfterRemoval); + expect(daosAfterRemoval.length).to.equal(0); + }) +}); diff --git a/test/Sector3Priority.ts b/test/Sector3Priority.ts index d75b1cc..16da73d 100644 --- a/test/Sector3Priority.ts +++ b/test/Sector3Priority.ts @@ -11,8 +11,8 @@ describe("Sector3DAOPriority", function () { // Contracts are deployed using the first signer/account by default const [owner, otherAccount] = await ethers.getSigners(); - console.log('owner.address:', owner.address); - console.log('otherAccount.address:', otherAccount.address); + // console.log('owner.address:', owner.address); + // console.log('otherAccount.address:', otherAccount.address); const Sector3DAOPriority = await ethers.getContractFactory("Sector3DAOPriority"); const dao = "0x96Bf89193E2A07720e42bA3AD736128a45537e63"; // Sector#3 @@ -35,6 +35,8 @@ describe("Sector3DAOPriority", function () { // Contracts are deployed using the first signer/account by default const [owner, otherAccount] = await ethers.getSigners(); + // console.log('owner.address:', owner.address); + // console.log('otherAccount.address:', otherAccount.address); const Sector3DAOPriority = await ethers.getContractFactory("Sector3DAOPriority"); const dao = "0x96Bf89193E2A07720e42bA3AD736128a45537e63"; // Sector#3 @@ -57,6 +59,8 @@ describe("Sector3DAOPriority", function () { // Contracts are deployed using the first signer/account by default const [owner, otherAccount] = await ethers.getSigners(); + // console.log('owner.address:', owner.address); + // console.log('otherAccount.address:', otherAccount.address); const Sector3DAOPriority = await ethers.getContractFactory("Sector3DAOPriority"); const dao = "0x96Bf89193E2A07720e42bA3AD736128a45537e63"; // Sector#3 @@ -80,8 +84,8 @@ describe("Sector3DAOPriority", function () { // Contracts are deployed using the first signer/account by default const [owner, otherAccount] = await ethers.getSigners(); - console.log('owner.address:', owner.address); - console.log('otherAccount.address:', otherAccount.address); + // console.log('owner.address:', owner.address); + // console.log('otherAccount.address:', otherAccount.address); const Sector3DAOPriority = await ethers.getContractFactory("Sector3DAOPriority"); const dao = "0x96Bf89193E2A07720e42bA3AD736128a45537e63"; // Sector#3 @@ -160,10 +164,10 @@ describe("Sector3DAOPriority", function () { const { sector3DAOPriority } = await loadFixture(deployWeeklyFixture); // Increase the time by 1 week - console.log("Current time:", await time.latest()); + // console.log("Current time:", await time.latest()); const ONE_WEEK_IN_SECONDS = 7 * 24 * 60 * 60; await time.increase(ONE_WEEK_IN_SECONDS); - console.log("Time 1 week later:", await time.latest()); + // console.log("Time 1 week later:", await time.latest()); expect(await sector3DAOPriority.getEpochIndex()).to.equal(1); }); @@ -181,10 +185,10 @@ describe("Sector3DAOPriority", function () { const { sector3DAOPriority } = await loadFixture(deployBiweeklyFixture); // Increase the time by 1 week - console.log("Current time:", await time.latest()); + // console.log("Current time:", await time.latest()); const ONE_WEEK_IN_SECONDS = 7 * 24 * 60 * 60; await time.increase(ONE_WEEK_IN_SECONDS); - console.log("Time 1 week later:", await time.latest()); + // console.log("Time 1 week later:", await time.latest()); expect(await sector3DAOPriority.getEpochIndex()).to.equal(0); }); @@ -193,10 +197,10 @@ describe("Sector3DAOPriority", function () { const { sector3DAOPriority } = await loadFixture(deployBiweeklyFixture); // Increase the time by 2 weeks - console.log("Current time:", await time.latest()); + // console.log("Current time:", await time.latest()); const ONE_WEEK_IN_SECONDS = 2 * 7 * 24 * 60 * 60; await time.increase(ONE_WEEK_IN_SECONDS); - console.log("Time 2 weeks later:", await time.latest()); + // console.log("Time 2 weeks later:", await time.latest()); expect(await sector3DAOPriority.getEpochIndex()).to.equal(1); }); @@ -205,10 +209,10 @@ describe("Sector3DAOPriority", function () { const { sector3DAOPriority } = await loadFixture(deployBiweeklyFixture); // Increase the time by 3 weeks - console.log("Current time:", await time.latest()); + // console.log("Current time:", await time.latest()); const ONE_WEEK_IN_SECONDS = 3 * 7 * 24 * 60 * 60; await time.increase(ONE_WEEK_IN_SECONDS); - console.log("Time 3 weeks later:", await time.latest()); + // console.log("Time 3 weeks later:", await time.latest()); expect(await sector3DAOPriority.getEpochIndex()).to.equal(1); }); @@ -217,10 +221,10 @@ describe("Sector3DAOPriority", function () { const { sector3DAOPriority } = await loadFixture(deployBiweeklyFixture); // Increase the time by 4 weeks - console.log("Current time:", await time.latest()); + // console.log("Current time:", await time.latest()); const ONE_WEEK_IN_SECONDS = 4 * 7 * 24 * 60 * 60; await time.increase(ONE_WEEK_IN_SECONDS); - console.log("Time 4 weeks later:", await time.latest()); + // console.log("Time 4 weeks later:", await time.latest()); expect(await sector3DAOPriority.getEpochIndex()).to.equal(2); }); @@ -238,10 +242,10 @@ describe("Sector3DAOPriority", function () { const { sector3DAOPriority } = await loadFixture(deployMonthlyFixture); // Increase the time by 1 week - console.log("Current time:", await time.latest()); + // console.log("Current time:", await time.latest()); const ONE_WEEK_IN_SECONDS = 7 * 24 * 60 * 60; await time.increase(ONE_WEEK_IN_SECONDS); - console.log("Time 1 week later:", await time.latest()); + // console.log("Time 1 week later:", await time.latest()); expect(await sector3DAOPriority.getEpochIndex()).to.equal(0); }); @@ -250,10 +254,10 @@ describe("Sector3DAOPriority", function () { const { sector3DAOPriority } = await loadFixture(deployMonthlyFixture); // Increase the time by 2 weeks - console.log("Current time:", await time.latest()); + // console.log("Current time:", await time.latest()); const ONE_WEEK_IN_SECONDS = 2 * 7 * 24 * 60 * 60; await time.increase(ONE_WEEK_IN_SECONDS); - console.log("Time 2 weeks later:", await time.latest()); + // console.log("Time 2 weeks later:", await time.latest()); expect(await sector3DAOPriority.getEpochIndex()).to.equal(0); }); @@ -262,10 +266,10 @@ describe("Sector3DAOPriority", function () { const { sector3DAOPriority } = await loadFixture(deployMonthlyFixture); // Increase the time by 3 weeks - console.log("Current time:", await time.latest()); + // console.log("Current time:", await time.latest()); const ONE_WEEK_IN_SECONDS = 3 * 7 * 24 * 60 * 60; await time.increase(ONE_WEEK_IN_SECONDS); - console.log("Time 3 weeks later:", await time.latest()); + // console.log("Time 3 weeks later:", await time.latest()); expect(await sector3DAOPriority.getEpochIndex()).to.equal(0); }); @@ -274,10 +278,10 @@ describe("Sector3DAOPriority", function () { const { sector3DAOPriority } = await loadFixture(deployMonthlyFixture); // Increase the time by 4 weeks - console.log("Current time:", await time.latest()); + // console.log("Current time:", await time.latest()); const ONE_WEEK_IN_SECONDS = 4 * 7 * 24 * 60 * 60; await time.increase(ONE_WEEK_IN_SECONDS); - console.log("Time 4 weeks later:", await time.latest()); + // console.log("Time 4 weeks later:", await time.latest()); expect(await sector3DAOPriority.getEpochIndex()).to.equal(1); }); @@ -285,173 +289,151 @@ describe("Sector3DAOPriority", function () { describe("addContribution", async function() { - it("getContributionCount - should be zero immediately after deployment", async function() { + it("getContributions - length should be zero immediately after deployment", async function() { const { sector3DAOPriority } = await loadFixture(deployWeeklyFixture); - - expect(await sector3DAOPriority.getContributionCount()).to.equal(0); + + const contributions = await sector3DAOPriority.getContributions() + expect(contributions.length).to.equal(0); }); - it("getContributionCount - should be 1 after first addition", async function() { + it("getContributions - length should be 1 after first addition", async function() { const { sector3DAOPriority, owner } = await loadFixture(deployWeeklyFixture); - const tx = await sector3DAOPriority.addContribution({ - timestamp: 2_049, - epochIndex: 2_049, - contributor: owner.address, - description: "Description (test)", - proofURL: "https://github.com/sector-3", - alignment: 3, // Alignment.Mostly - alignmentPercentage: 3 * 20, - hoursSpent: 10 - }); - console.log("tx:", tx); + const tx = await sector3DAOPriority.addContribution( + "Description (test)", + "https://github.com/sector-3", + 10, + 60 + ); + // console.log("tx:", tx); - expect(await sector3DAOPriority.getContributionCount()).to.equal(1); + const contributions = await sector3DAOPriority.getContributions() + expect(contributions.length).to.equal(1); }); - it("getContributionCount - should be 2 after second addition", async function() { + it("getContributions - length should be 2 after second addition", async function() { const { sector3DAOPriority, owner } = await loadFixture(deployWeeklyFixture); - await sector3DAOPriority.addContribution({ - timestamp: 2_049, - epochIndex: 2_049, - contributor: owner.address, - description: "Description (test)", - proofURL: "https://github.com/sector-3", - alignment: 3, // Alignment.Mostly - alignmentPercentage: 3 * 20, - hoursSpent: 10 - }); - - await sector3DAOPriority.addContribution({ - timestamp: 2_049, - epochIndex: 2_049, - contributor: owner.address, - description: "Description (test)", - proofURL: "https://github.com/sector-3", - alignment: 3, // Alignment.Mostly - alignmentPercentage: 3 * 20, - hoursSpent: 10 - }); - - expect(await sector3DAOPriority.getContributionCount()).to.equal(2); + await sector3DAOPriority.addContribution( + "Description (test)", + "https://github.com/sector-3", + 10, + 60 + ); + + await sector3DAOPriority.addContribution( + "Description (test)", + "https://github.com/sector-3", + 10, + 60 + ); + + const contributions = await sector3DAOPriority.getContributions() + expect(contributions.length).to.equal(2); }); it("addContribution", async function() { const { sector3DAOPriority, owner } = await loadFixture(deployWeeklyFixture); - await sector3DAOPriority.addContribution({ - timestamp: 2_049, - epochIndex: 2_049, - contributor: owner.address, - description: "Description (test)", - proofURL: "https://github.com/sector-3", - alignment: 3, // Alignment.Mostly - alignmentPercentage: 3 * 20, - hoursSpent: 10 - }); + await sector3DAOPriority.addContribution( + "Description (test)", + "https://github.com/sector-3", + 10, + 60 + ); - const contribution = await sector3DAOPriority.getContribution(0); - console.log("contribution:", contribution) + const contributions = await sector3DAOPriority.getContributions(); + const contribution = contributions[0]; + // console.log("contribution:", contribution); expect(contribution.epochIndex).to.equal(0); expect(contribution.contributor).to.equal(owner.address); expect(contribution.description).to.equal("Description (test)"); - expect(contribution.alignment).to.equal(3); expect(contribution.hoursSpent).to.equal(10); + expect(contribution.alignmentPercentage).to.equal(60); }); it("addContribution - 2nd epoch", async function() { const { sector3DAOPriority, owner } = await loadFixture(deployWeeklyFixture); // Increase the time by 1 week - console.log("Current time:", await time.latest()); + // console.log("Current time:", await time.latest()); const ONE_WEEK_IN_SECONDS = 7 * 24 * 60 * 60; await time.increase(ONE_WEEK_IN_SECONDS); - console.log("Time 1 week later:", await time.latest()); - - await sector3DAOPriority.addContribution({ - timestamp: 2_049, - epochIndex: 2_049, - contributor: owner.address, - description: "Description (test)", - proofURL: "https://github.com/sector-3", - alignment: 3, // Alignment.Mostly - alignmentPercentage: 3 * 20, - hoursSpent: 10 - }); - - const contribution = await sector3DAOPriority.getContribution(0); - console.log("contribution:", contribution) + // console.log("Time 1 week later:", await time.latest()); + + await sector3DAOPriority.addContribution( + "Description (test)", + "https://github.com/sector-3", + 10, + 60 + ); + + const contributions = await sector3DAOPriority.getContributions(); + const contribution = contributions[0]; + // console.log("contribution:", contribution); expect(contribution.epochIndex).to.equal(1); expect(contribution.contributor).to.equal(owner.address); expect(contribution.description).to.equal("Description (test)"); - expect(contribution.alignment).to.equal(3); expect(contribution.hoursSpent).to.equal(10); + expect(contribution.alignmentPercentage).to.equal(60); }); it("addContribution - 2nd epoch, 2nd contribution", async function() { const { sector3DAOPriority, owner } = await loadFixture(deployWeeklyFixture); // Increase the time by 1 week - console.log("Current time:", await time.latest()); + // console.log("Current time:", await time.latest()); const ONE_WEEK_IN_SECONDS = 7 * 24 * 60 * 60; await time.increase(ONE_WEEK_IN_SECONDS); - console.log("Time 1 week later:", await time.latest()); - - await sector3DAOPriority.addContribution({ - timestamp: 2_049, - epochIndex: 2_049, - contributor: owner.address, - description: "Description (test)", - proofURL: "https://github.com/sector-3", - alignment: 3, // Alignment.Mostly - alignmentPercentage: 3 * 20, - hoursSpent: 10 - }); - - await sector3DAOPriority.addContribution({ - timestamp: 2_049, - epochIndex: 2_049, - contributor: owner.address, - description: "Description 2 (test)", - proofURL: "https://github.com/sector-3", - alignment: 4, // Alignment.Highly - alignmentPercentage: 4 * 20, - hoursSpent: 12 - }); - - const contribution1 = await sector3DAOPriority.getContribution(0); - console.log("contribution1:", contribution1) + // console.log("Time 1 week later:", await time.latest()); + + await sector3DAOPriority.addContribution( + "Description (test)", + "https://github.com/sector-3", + 10, + 60 + ); + + await sector3DAOPriority.addContribution( + "Description 2 (test)", + "https://github.com/sector-3", + 12, + 80 + ); + + const contributions = await sector3DAOPriority.getContributions(); + const contribution1 = contributions[0]; + // console.log("contribution1:", contribution1); expect(contribution1.epochIndex).to.equal(1); expect(contribution1.contributor).to.equal(owner.address); expect(contribution1.description).to.equal("Description (test)"); - expect(contribution1.alignment).to.equal(3); expect(contribution1.hoursSpent).to.equal(10); + expect(contribution1.alignmentPercentage).to.equal(60); - const contribution2 = await sector3DAOPriority.getContribution(1); - console.log("contribution2:", contribution2) + const contribution2 = contributions[1]; + // console.log("contribution2:", contribution2); expect(contribution2.epochIndex).to.equal(1); expect(contribution2.contributor).to.equal(owner.address); expect(contribution2.description).to.equal("Description 2 (test)"); - expect(contribution2.alignment).to.equal(4); expect(contribution2.hoursSpent).to.equal(12); + expect(contribution2.alignmentPercentage).to.equal(80); }); }); - describe("NFT gating - addContribution2", async function() { + describe("NFT gating - addContribution", async function() { it("should fail if NFT gating", async function() { const { sector3DAOPriority, owner } = await loadFixture(deployWeeklyFixtureWithNFTGating); - await expect(sector3DAOPriority.addContribution2( + await expect(sector3DAOPriority.addContribution( "Description (test)", "https://github.com/sector-3", 10, - 3 // Alignment.Mostly + 60 )).to.be.revertedWithCustomError( sector3DAOPriority, "NoGatingNFTOwnership" @@ -462,14 +444,16 @@ describe("Sector3DAOPriority", function () { const { sector3DAOPriority, owner, gatingNFT } = await loadFixture(deployWeeklyFixtureWithNFTGating); await gatingNFT.safeMint(owner.address); - - await sector3DAOPriority.addContribution2( + + await sector3DAOPriority.addContribution( "Description (test)", "https://github.com/sector-3", 10, - 3 // Alignment.Mostly + 60 ); - expect(await sector3DAOPriority.getContributionCount()).to.equal(1); + + const contributions = await sector3DAOPriority.getContributions() + expect(contributions.length).to.equal(1); }); }); @@ -478,36 +462,28 @@ describe("Sector3DAOPriority", function () { it("Should be 100% if one contributor", async function() { const { sector3DAOPriority, owner } = await loadFixture(deployWeeklyFixture); - await sector3DAOPriority.addContribution({ - timestamp: 2_049, - epochIndex: 2_049, - contributor: owner.address, - description: "Description (test)", - proofURL: "https://github.com/sector-3", - alignment: 3, // Alignment.Mostly - alignmentPercentage: 3 * 20, - hoursSpent: 5 - }); - - await sector3DAOPriority.addContribution({ - timestamp: 2_049, - epochIndex: 2_049, - contributor: owner.address, - description: "Description #2", - proofURL: "https://github.com/sector-3", - alignment: 3, // Alignment.Mostly - alignmentPercentage: 3 * 20, - hoursSpent: 5 - }); + await sector3DAOPriority.addContribution( + "Description (test)", + "https://github.com/sector-3", + 5, + 60 + ); + + await sector3DAOPriority.addContribution( + "Description (test)", + "https://github.com/sector-3", + 5, + 60 + ); // Increase the time by 1 week - console.log("Current time:", await time.latest()); + // console.log("Current time:", await time.latest()); const ONE_WEEK_IN_SECONDS = 7 * 24 * 60 * 60; await time.increase(ONE_WEEK_IN_SECONDS); - console.log("Time 1 week later:", await time.latest()); + // console.log("Time 1 week later:", await time.latest()); const allocationPercentage = await sector3DAOPriority.getAllocationPercentage(0, owner.address); - console.log("allocationPercentage:", allocationPercentage); + // console.log("allocationPercentage:", allocationPercentage); expect(allocationPercentage).to.equal(100); }); @@ -515,36 +491,28 @@ describe("Sector3DAOPriority", function () { it("Should be 50% if two contributors", async function() { const { sector3DAOPriority, owner, otherAccount } = await loadFixture(deployWeeklyFixture); - await sector3DAOPriority.addContribution({ - timestamp: 2_049, - epochIndex: 2_049, - contributor: owner.address, - description: "Description #1", - proofURL: "https://github.com/sector-3", - alignment: 3, // Alignment.Mostly - alignmentPercentage: 3 * 20, - hoursSpent: 5 - }); - - await sector3DAOPriority.connect(otherAccount).addContribution({ - timestamp: 2_049, - epochIndex: 2_049, - contributor: owner.address, - description: "Description #2", - proofURL: "https://github.com/sector-3", - alignment: 3, // Alignment.Mostly - alignmentPercentage: 3 * 20, - hoursSpent: 5 - }); + await sector3DAOPriority.addContribution( + "Description #1", + "https://github.com/sector-3", + 5, + 60 + ); + + await sector3DAOPriority.connect(otherAccount).addContribution( + "Description (test)", + "https://github.com/sector-3", + 5, + 60 + ); // Increase the time by 1 week - console.log("Current time:", await time.latest()); + // console.log("Current time:", await time.latest()); const ONE_WEEK_IN_SECONDS = 7 * 24 * 60 * 60; await time.increase(ONE_WEEK_IN_SECONDS); - console.log("Time 1 week later:", await time.latest()); + // console.log("Time 1 week later:", await time.latest()); const allocationPercentage = await sector3DAOPriority.getAllocationPercentage(0, owner.address); - console.log("allocationPercentage:", allocationPercentage); + // console.log("allocationPercentage:", allocationPercentage); expect(allocationPercentage).to.equal(50); }); @@ -555,36 +523,28 @@ describe("Sector3DAOPriority", function () { it("Should be 2.049 if one contributor", async function() { const { sector3DAOPriority, owner } = await loadFixture(deployWeeklyFixture); - await sector3DAOPriority.addContribution({ - timestamp: 2_049, - epochIndex: 2_049, - contributor: owner.address, - description: "Description #1", - proofURL: "https://github.com/sector-3", - alignment: 3, // Alignment.Mostly - alignmentPercentage: 3 * 20, - hoursSpent: 5 - }); - - await sector3DAOPriority.addContribution({ - timestamp: 2_049, - epochIndex: 2_049, - contributor: owner.address, - description: "Description #1", - proofURL: "https://github.com/sector-3", - alignment: 3, // Alignment.Mostly - alignmentPercentage: 3 * 20, - hoursSpent: 5 - }); + await sector3DAOPriority.addContribution( + "Description #1", + "https://github.com/sector-3", + 5, + 60 + ); + + await sector3DAOPriority.addContribution( + "Description #1", + "https://github.com/sector-3", + 5, + 60 + ); // Increase the time by 1 week - console.log("Current time:", await time.latest()); + // console.log("Current time:", await time.latest()); const ONE_WEEK_IN_SECONDS = 7 * 24 * 60 * 60; await time.increase(ONE_WEEK_IN_SECONDS); - console.log("Time 1 week later:", await time.latest()); + // console.log("Time 1 week later:", await time.latest()); const epochReward = await sector3DAOPriority.getEpochReward(0, owner.address); - console.log("epochReward:", epochReward); + // console.log("epochReward:", epochReward); expect(epochReward).to.equal(ethers.utils.parseUnits("2.049")); }); @@ -592,36 +552,28 @@ describe("Sector3DAOPriority", function () { it("Should be 1.0245 if two contributors", async function() { const { sector3DAOPriority, owner, otherAccount } = await loadFixture(deployWeeklyFixture); - await sector3DAOPriority.addContribution({ - timestamp: 2_049, - epochIndex: 2_049, - contributor: owner.address, - description: "Description #1", - proofURL: "https://github.com/sector-3", - alignment: 3, // Alignment.Mostly - alignmentPercentage: 3 * 20, - hoursSpent: 5 - }); - - await sector3DAOPriority.connect(otherAccount).addContribution({ - timestamp: 2_049, - epochIndex: 2_049, - contributor: owner.address, - description: "Description #2", - proofURL: "https://github.com/sector-3", - alignment: 3, // Alignment.Mostly - alignmentPercentage: 3 * 20, - hoursSpent: 5 - }); + await sector3DAOPriority.addContribution( + "Description #1", + "https://github.com/sector-3", + 5, + 60 + ); + + await sector3DAOPriority.connect(otherAccount).addContribution( + "Description #2", + "https://github.com/sector-3", + 5, + 60 + ); // Increase the time by 1 week - console.log("Current time:", await time.latest()); + // console.log("Current time:", await time.latest()); const ONE_WEEK_IN_SECONDS = 7 * 24 * 60 * 60; await time.increase(ONE_WEEK_IN_SECONDS); - console.log("Time 1 week later:", await time.latest()); + // console.log("Time 1 week later:", await time.latest()); const epochReward = await sector3DAOPriority.getEpochReward(0, owner.address); - console.log("epochReward:", epochReward); + // console.log("epochReward:", epochReward); expect(epochReward).to.equal(ethers.utils.parseUnits("1.0245")); }); @@ -632,16 +584,12 @@ describe("Sector3DAOPriority", function () { it("Should revert if epoch not yet ended", async function() { const { sector3DAOPriority, owner } = await loadFixture(deployWeeklyFixture); - await sector3DAOPriority.addContribution({ - timestamp: 2_049, - epochIndex: 2_049, - contributor: owner.address, - description: "Description #1", - proofURL: "https://github.com/sector-3", - alignment: 3, // Alignment.Mostly - alignmentPercentage: 3 * 20, - hoursSpent: 5 - }); + await sector3DAOPriority.addContribution( + "Description #1", + "https://github.com/sector-3", + 5, + 60 + ); await expect(sector3DAOPriority.claimReward(0)).to.be.revertedWithCustomError( sector3DAOPriority, @@ -653,10 +601,10 @@ describe("Sector3DAOPriority", function () { const { sector3DAOPriority, owner } = await loadFixture(deployWeeklyFixture); // Increase the time by 1 week - console.log("Current time:", await time.latest()); + // console.log("Current time:", await time.latest()); const ONE_WEEK_IN_SECONDS = 7 * 24 * 60 * 60; await time.increase(ONE_WEEK_IN_SECONDS); - console.log("Time 1 week later:", await time.latest()); + // console.log("Time 1 week later:", await time.latest()); await expect(sector3DAOPriority.claimReward(0)).to.be.revertedWithCustomError( sector3DAOPriority, @@ -667,22 +615,18 @@ describe("Sector3DAOPriority", function () { it("Claim 100%", async function() { const { sector3DAOPriority, owner, rewardToken } = await loadFixture(deployWeeklyFixture); - await sector3DAOPriority.addContribution({ - timestamp: 2_049, - epochIndex: 2_049, - contributor: owner.address, - description: "Description #1", - proofURL: "https://github.com/sector-3", - alignment: 3, // Alignment.Mostly - alignmentPercentage: 3 * 20, - hoursSpent: 5 - }); + await sector3DAOPriority.addContribution( + "Description #1", + "https://github.com/sector-3", + 5, + 60 + ); // Increase the time by 1 week - console.log("Current time:", await time.latest()); + // console.log("Current time:", await time.latest()); const ONE_WEEK_IN_SECONDS = 7 * 24 * 60 * 60; await time.increase(ONE_WEEK_IN_SECONDS); - console.log("Time 1 week later:", await time.latest()); + // console.log("Time 1 week later:", await time.latest()); // Transfer funding to the contract rewardToken.transfer(sector3DAOPriority.address, ethers.utils.parseUnits("2.049")); @@ -696,33 +640,25 @@ describe("Sector3DAOPriority", function () { it("Claim 50%", async function() { const { sector3DAOPriority, owner, otherAccount, rewardToken } = await loadFixture(deployWeeklyFixture); - await sector3DAOPriority.addContribution({ - timestamp: 2_049, - epochIndex: 2_049, - contributor: owner.address, - description: "Description #1", - proofURL: "https://github.com/sector-3", - alignment: 3, // Alignment.Mostly - alignmentPercentage: 3 * 20, - hoursSpent: 5 - }); - - await sector3DAOPriority.connect(otherAccount).addContribution({ - timestamp: 2_049, - epochIndex: 2_049, - contributor: owner.address, - description: "Description #2", - proofURL: "https://github.com/sector-3", - alignment: 3, // Alignment.Mostly - alignmentPercentage: 3 * 20, - hoursSpent: 5 - }); + await sector3DAOPriority.addContribution( + "Description #1", + "https://github.com/sector-3", + 5, + 60 + ); + + await sector3DAOPriority.connect(otherAccount).addContribution( + "Description #2", + "https://github.com/sector-3", + 5, + 60 + ); // Increase the time by 1 week - console.log("Current time:", await time.latest()); + // console.log("Current time:", await time.latest()); const ONE_WEEK_IN_SECONDS = 7 * 24 * 60 * 60; await time.increase(ONE_WEEK_IN_SECONDS); - console.log("Time 1 week later:", await time.latest()); + // console.log("Time 1 week later:", await time.latest()); // Transfer funding to the contract rewardToken.transfer(sector3DAOPriority.address, ethers.utils.parseUnits("2.049")); From b63d76b49005ed18a54101ede70e473b1c99df7d Mon Sep 17 00:00:00 2001 From: aahna-ashina <95955389+aahna-ashina@users.noreply.github.com> Date: Sun, 12 Mar 2023 17:14:05 +0800 Subject: [PATCH 07/17] chore: upgrade solidity --- contracts/Lock.sol | 34 ------ contracts/governance/Sector3Governor.sol | 2 +- contracts/protocol/IPriority.sol | 2 +- contracts/protocol/Sector3DAO.sol | 2 +- contracts/protocol/Sector3DAOFactory.sol | 2 +- contracts/protocol/Sector3DAOPriority.sol | 2 +- contracts/protocol/Structs.sol | 2 +- contracts/token/Sector3Dove.sol | 2 +- hardhat.config.ts | 2 +- scripts/deploy-lock.ts | 25 ----- test/Lock.ts | 124 ---------------------- 11 files changed, 8 insertions(+), 191 deletions(-) delete mode 100644 contracts/Lock.sol delete mode 100644 scripts/deploy-lock.ts delete mode 100644 test/Lock.ts diff --git a/contracts/Lock.sol b/contracts/Lock.sol deleted file mode 100644 index 50935f6..0000000 --- a/contracts/Lock.sol +++ /dev/null @@ -1,34 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.9; - -// Uncomment this line to use console.log -// import "hardhat/console.sol"; - -contract Lock { - uint public unlockTime; - address payable public owner; - - event Withdrawal(uint amount, uint when); - - constructor(uint _unlockTime) payable { - require( - block.timestamp < _unlockTime, - "Unlock time should be in the future" - ); - - unlockTime = _unlockTime; - owner = payable(msg.sender); - } - - function withdraw() public { - // Uncomment this line, and the import of "hardhat/console.sol", to print a log in your terminal - // console.log("Unlock time is %o and block timestamp is %o", unlockTime, block.timestamp); - - require(block.timestamp >= unlockTime, "You can't withdraw yet"); - require(msg.sender == owner, "You aren't the owner"); - - emit Withdrawal(address(this).balance, block.timestamp); - - owner.transfer(address(this).balance); - } -} diff --git a/contracts/governance/Sector3Governor.sol b/contracts/governance/Sector3Governor.sol index 34b3d3f..350ae4d 100644 --- a/contracts/governance/Sector3Governor.sol +++ b/contracts/governance/Sector3Governor.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.17; +pragma solidity ^0.8.19; import "@openzeppelin/contracts/governance/Governor.sol"; import "@openzeppelin/contracts/governance/extensions/GovernorSettings.sol"; diff --git a/contracts/protocol/IPriority.sol b/contracts/protocol/IPriority.sol index 46e3ba0..0d55e9f 100644 --- a/contracts/protocol/IPriority.sol +++ b/contracts/protocol/IPriority.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.17; +pragma solidity ^0.8.19; interface IPriority { diff --git a/contracts/protocol/Sector3DAO.sol b/contracts/protocol/Sector3DAO.sol index 27f1c65..10d0aff 100644 --- a/contracts/protocol/Sector3DAO.sol +++ b/contracts/protocol/Sector3DAO.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.17; +pragma solidity ^0.8.19; import './Sector3DAOPriority.sol'; diff --git a/contracts/protocol/Sector3DAOFactory.sol b/contracts/protocol/Sector3DAOFactory.sol index de3426c..529fd63 100644 --- a/contracts/protocol/Sector3DAOFactory.sol +++ b/contracts/protocol/Sector3DAOFactory.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.17; +pragma solidity ^0.8.19; import './Sector3DAO.sol'; diff --git a/contracts/protocol/Sector3DAOPriority.sol b/contracts/protocol/Sector3DAOPriority.sol index 29fa822..6f84cd1 100644 --- a/contracts/protocol/Sector3DAOPriority.sol +++ b/contracts/protocol/Sector3DAOPriority.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.17; +pragma solidity ^0.8.19; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; diff --git a/contracts/protocol/Structs.sol b/contracts/protocol/Structs.sol index b507cee..c7b7534 100644 --- a/contracts/protocol/Structs.sol +++ b/contracts/protocol/Structs.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.17; +pragma solidity ^0.8.19; struct Contribution { uint256 timestamp; diff --git a/contracts/token/Sector3Dove.sol b/contracts/token/Sector3Dove.sol index c06e616..d12ab90 100644 --- a/contracts/token/Sector3Dove.sol +++ b/contracts/token/Sector3Dove.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.17; +pragma solidity ^0.8.19; import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol"; diff --git a/hardhat.config.ts b/hardhat.config.ts index 59480fe..479c0cb 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -5,7 +5,7 @@ import "@nomiclabs/hardhat-etherscan"; const config: HardhatUserConfig = { solidity: { - version: "0.8.17", + version: "0.8.19", settings: { optimizer: { enabled: true, diff --git a/scripts/deploy-lock.ts b/scripts/deploy-lock.ts deleted file mode 100644 index 940bd20..0000000 --- a/scripts/deploy-lock.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { ethers } from "hardhat"; - -async function main() { - console.log('Deploying Lock.sol') - - const currentTimestampInSeconds = Math.round(Date.now() / 1000); - const ONE_YEAR_IN_SECS = 365 * 24 * 60 * 60; - const unlockTime = currentTimestampInSeconds + ONE_YEAR_IN_SECS; - - const lockedAmount = ethers.utils.parseEther("1"); - - const Lock = await ethers.getContractFactory("Lock"); - const lock = await Lock.deploy(unlockTime, { value: lockedAmount }); - - await lock.deployed(); - - console.log(`Lock with 1 ETH and unlock timestamp ${unlockTime} deployed to ${lock.address}`); -} - -// We recommend this pattern to be able to use async/await everywhere -// and properly handle errors. -main().catch((error) => { - console.error(error); - process.exitCode = 1; -}); diff --git a/test/Lock.ts b/test/Lock.ts deleted file mode 100644 index 92e0dc7..0000000 --- a/test/Lock.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { time, loadFixture } from "@nomicfoundation/hardhat-network-helpers"; -import { anyValue } from "@nomicfoundation/hardhat-chai-matchers/withArgs"; -import { expect } from "chai"; -import { ethers } from "hardhat"; - -describe("Lock", function () { - // We define a fixture to reuse the same setup in every test. - // We use loadFixture to run this setup once, snapshot that state, - // and reset Hardhat Network to that snapshot in every test. - async function deployOneYearLockFixture() { - const ONE_YEAR_IN_SECS = 365 * 24 * 60 * 60; - const ONE_GWEI = 1_000_000_000; - - const lockedAmount = ONE_GWEI; - const unlockTime = (await time.latest()) + ONE_YEAR_IN_SECS; - - // Contracts are deployed using the first signer/account by default - const [owner, otherAccount] = await ethers.getSigners(); - - const Lock = await ethers.getContractFactory("Lock"); - const lock = await Lock.deploy(unlockTime, { value: lockedAmount }); - - return { lock, unlockTime, lockedAmount, owner, otherAccount }; - } - - describe("Deployment", function () { - it("Should set the right unlockTime", async function () { - const { lock, unlockTime } = await loadFixture(deployOneYearLockFixture); - - expect(await lock.unlockTime()).to.equal(unlockTime); - }); - - it("Should set the right owner", async function () { - const { lock, owner } = await loadFixture(deployOneYearLockFixture); - - expect(await lock.owner()).to.equal(owner.address); - }); - - it("Should receive and store the funds to lock", async function () { - const { lock, lockedAmount } = await loadFixture( - deployOneYearLockFixture - ); - - expect(await ethers.provider.getBalance(lock.address)).to.equal( - lockedAmount - ); - }); - - it("Should fail if the unlockTime is not in the future", async function () { - // We don't use the fixture here because we want a different deployment - const latestTime = await time.latest(); - const Lock = await ethers.getContractFactory("Lock"); - await expect(Lock.deploy(latestTime, { value: 1 })).to.be.revertedWith( - "Unlock time should be in the future" - ); - }); - }); - - describe("Withdrawals", function () { - describe("Validations", function () { - it("Should revert with the right error if called too soon", async function () { - const { lock } = await loadFixture(deployOneYearLockFixture); - - await expect(lock.withdraw()).to.be.revertedWith( - "You can't withdraw yet" - ); - }); - - it("Should revert with the right error if called from another account", async function () { - const { lock, unlockTime, otherAccount } = await loadFixture( - deployOneYearLockFixture - ); - - // We can increase the time in Hardhat Network - await time.increaseTo(unlockTime); - - // We use lock.connect() to send a transaction from another account - await expect(lock.connect(otherAccount).withdraw()).to.be.revertedWith( - "You aren't the owner" - ); - }); - - it("Shouldn't fail if the unlockTime has arrived and the owner calls it", async function () { - const { lock, unlockTime } = await loadFixture( - deployOneYearLockFixture - ); - - // Transactions are sent using the first signer by default - await time.increaseTo(unlockTime); - - await expect(lock.withdraw()).not.to.be.reverted; - }); - }); - - describe("Events", function () { - it("Should emit an event on withdrawals", async function () { - const { lock, unlockTime, lockedAmount } = await loadFixture( - deployOneYearLockFixture - ); - - await time.increaseTo(unlockTime); - - await expect(lock.withdraw()) - .to.emit(lock, "Withdrawal") - .withArgs(lockedAmount, anyValue); // We accept any value as `when` arg - }); - }); - - describe("Transfers", function () { - it("Should transfer the funds to the owner", async function () { - const { lock, unlockTime, lockedAmount, owner } = await loadFixture( - deployOneYearLockFixture - ); - - await time.increaseTo(unlockTime); - - await expect(lock.withdraw()).to.changeEtherBalances( - [owner, lock], - [lockedAmount, -lockedAmount] - ); - }); - }); - }); -}); From f7f5bcedeb3d18440139465ee9a48948537b8f4a Mon Sep 17 00:00:00 2001 From: aahna-ashina <95955389+aahna-ashina@users.noreply.github.com> Date: Sun, 12 Mar 2023 17:22:10 +0800 Subject: [PATCH 08/17] chore: upgrade dependencies --- package-lock.json | 40 ++++++++++++++++++++-------------------- package.json | 6 +++--- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/package-lock.json b/package-lock.json index f383762..68858ac 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,19 +1,19 @@ { "name": "section3-contracts", - "version": "1.0.0", + "version": "1.0.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "section3-contracts", - "version": "1.0.0", + "version": "1.0.1", "license": "MIT", "devDependencies": { "@nomicfoundation/hardhat-toolbox": "^2.0.2", - "@nomiclabs/hardhat-etherscan": "^3.1.4", + "@nomiclabs/hardhat-etherscan": "^3.1.7", "@openzeppelin/contracts": "^4.8.2", "dotenv": "^16.0.3", - "hardhat": "^2.12.7" + "hardhat": "^2.13.0" } }, "node_modules/@cspotcode/source-map-support": { @@ -1555,9 +1555,9 @@ } }, "node_modules/@nomiclabs/hardhat-etherscan": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-3.1.4.tgz", - "integrity": "sha512-fw8JCfukf6MdIGoySRmSftlM2wBgoaSbWQZgiYfD/KTeaSFEWCdMpuPZcLSBXtwtnQyyWDs07Lo7fL8HSqtD2Q==", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-3.1.7.tgz", + "integrity": "sha512-tZ3TvSgpvsQ6B6OGmo1/Au6u8BrAkvs1mIC/eURA3xgIfznUZBhmpne8hv7BXUzw9xNL3fXdpOYgOQlVMTcoHQ==", "dev": true, "dependencies": { "@ethersproject/abi": "^5.1.2", @@ -1569,7 +1569,7 @@ "lodash": "^4.17.11", "semver": "^6.3.0", "table": "^6.8.0", - "undici": "^5.4.0" + "undici": "^5.14.0" }, "peerDependencies": { "hardhat": "^2.0.4" @@ -4724,9 +4724,9 @@ } }, "node_modules/hardhat": { - "version": "2.12.7", - "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.12.7.tgz", - "integrity": "sha512-voWoN6zn5d8BOEaczSyK/1PyfdeOeI3SbGCFb36yCHTJUt6OIqLb+ZDX30VhA1UsYKzLqG7UnWl3fKJUuANc6A==", + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.13.0.tgz", + "integrity": "sha512-ZlzBOLML1QGlm6JWyVAG8lVTEAoOaVm1in/RU2zoGAnYEoD1Rp4T+ZMvrLNhHaaeS9hfjJ1gJUBfiDr4cx+htQ==", "dev": true, "dependencies": { "@ethersproject/abi": "^5.1.2", @@ -4781,10 +4781,10 @@ "ws": "^7.4.6" }, "bin": { - "hardhat": "internal/cli/cli.js" + "hardhat": "internal/cli/bootstrap.js" }, "engines": { - "node": "^14.0.0 || ^16.0.0 || ^18.0.0" + "node": ">=14.0.0" }, "peerDependencies": { "ts-node": "*", @@ -10156,9 +10156,9 @@ "requires": {} }, "@nomiclabs/hardhat-etherscan": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-3.1.4.tgz", - "integrity": "sha512-fw8JCfukf6MdIGoySRmSftlM2wBgoaSbWQZgiYfD/KTeaSFEWCdMpuPZcLSBXtwtnQyyWDs07Lo7fL8HSqtD2Q==", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-3.1.7.tgz", + "integrity": "sha512-tZ3TvSgpvsQ6B6OGmo1/Au6u8BrAkvs1mIC/eURA3xgIfznUZBhmpne8hv7BXUzw9xNL3fXdpOYgOQlVMTcoHQ==", "dev": true, "requires": { "@ethersproject/abi": "^5.1.2", @@ -10170,7 +10170,7 @@ "lodash": "^4.17.11", "semver": "^6.3.0", "table": "^6.8.0", - "undici": "^5.4.0" + "undici": "^5.14.0" } }, "@openzeppelin/contracts": { @@ -12697,9 +12697,9 @@ } }, "hardhat": { - "version": "2.12.7", - "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.12.7.tgz", - "integrity": "sha512-voWoN6zn5d8BOEaczSyK/1PyfdeOeI3SbGCFb36yCHTJUt6OIqLb+ZDX30VhA1UsYKzLqG7UnWl3fKJUuANc6A==", + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.13.0.tgz", + "integrity": "sha512-ZlzBOLML1QGlm6JWyVAG8lVTEAoOaVm1in/RU2zoGAnYEoD1Rp4T+ZMvrLNhHaaeS9hfjJ1gJUBfiDr4cx+htQ==", "dev": true, "requires": { "@ethersproject/abi": "^5.1.2", diff --git a/package.json b/package.json index 92aa3b6..3133cbf 100644 --- a/package.json +++ b/package.json @@ -1,15 +1,15 @@ { "name": "section3-contracts", - "version": "1.0.0", + "version": "1.0.1", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "license": "MIT", "devDependencies": { "@nomicfoundation/hardhat-toolbox": "^2.0.2", - "@nomiclabs/hardhat-etherscan": "^3.1.4", + "@nomiclabs/hardhat-etherscan": "^3.1.7", "@openzeppelin/contracts": "^4.8.2", "dotenv": "^16.0.3", - "hardhat": "^2.12.7" + "hardhat": "^2.13.0" } } From 0d6e180ace0ac344eeddd4f4a838054f5d610d8c Mon Sep 17 00:00:00 2001 From: aahna-ashina <95955389+aahna-ashina@users.noreply.github.com> Date: Sun, 12 Mar 2023 18:37:51 +0800 Subject: [PATCH 09/17] feat: keep record of claims (#15) --- contracts/protocol/Sector3DAOPriority.sol | 14 ++ test/Sector3Priority.ts | 158 +++++++++++++++++++++- 2 files changed, 170 insertions(+), 2 deletions(-) diff --git a/contracts/protocol/Sector3DAOPriority.sol b/contracts/protocol/Sector3DAOPriority.sol index 6f84cd1..9d982da 100644 --- a/contracts/protocol/Sector3DAOPriority.sol +++ b/contracts/protocol/Sector3DAOPriority.sol @@ -17,12 +17,14 @@ contract Sector3DAOPriority is IPriority { uint256 public immutable epochBudget; IERC721 public immutable gatingNFT; Contribution[] contributions; + mapping(uint16 => mapping(address => bool)) claims; event ContributionAdded(Contribution contribution); event RewardClaimed(uint16 epochIndex, address contributor, uint256 amount); error EpochNotYetEnded(); error NoRewardForEpoch(); + error RewardAlreadyClaimed(); error NoGatingNFTOwnership(); constructor(address dao_, string memory title_, address rewardToken_, uint16 epochDurationInDays, uint256 epochBudget_, address gatingNFT_) { @@ -80,7 +82,12 @@ contract Sector3DAOPriority is IPriority { if (epochReward == 0) { revert NoRewardForEpoch(); } + bool rewardClaimed = isRewardClaimed(epochIndex, msg.sender); + if (rewardClaimed) { + revert RewardAlreadyClaimed(); + } rewardToken.transfer(msg.sender, epochReward); + claims[epochIndex][msg.sender] = true; emit RewardClaimed(epochIndex, msg.sender, epochReward); } @@ -94,6 +101,13 @@ contract Sector3DAOPriority is IPriority { return epochBudget * allocationPercentage / 100; } + /** + * Checks if a contributor's reward has been claimed for a given epoch. + */ + function isRewardClaimed(uint16 epochIndex, address contributor) public view returns (bool) { + return claims[epochIndex][contributor]; + } + /** * Calculates a contributor's percentage allocation of the budget for a given epoch. * diff --git a/test/Sector3Priority.ts b/test/Sector3Priority.ts index 16da73d..f08c1dc 100644 --- a/test/Sector3Priority.ts +++ b/test/Sector3Priority.ts @@ -629,7 +629,7 @@ describe("Sector3DAOPriority", function () { // console.log("Time 1 week later:", await time.latest()); // Transfer funding to the contract - rewardToken.transfer(sector3DAOPriority.address, ethers.utils.parseUnits("2.049")); + await rewardToken.transfer(sector3DAOPriority.address, ethers.utils.parseUnits("2.049")); expect(await rewardToken.balanceOf(sector3DAOPriority.address)).to.equal(ethers.utils.parseUnits("2.049")); // Claim reward @@ -661,7 +661,7 @@ describe("Sector3DAOPriority", function () { // console.log("Time 1 week later:", await time.latest()); // Transfer funding to the contract - rewardToken.transfer(sector3DAOPriority.address, ethers.utils.parseUnits("2.049")); + await rewardToken.transfer(sector3DAOPriority.address, ethers.utils.parseUnits("2.049")); expect(await rewardToken.balanceOf(sector3DAOPriority.address)).to.equal(ethers.utils.parseUnits("2.049")); // Claim reward (owner account) @@ -674,5 +674,159 @@ describe("Sector3DAOPriority", function () { expect(await rewardToken.balanceOf(sector3DAOPriority.address)).to.equal(0); expect(await rewardToken.balanceOf(otherAccount.address)).to.equal(ethers.utils.parseUnits("1.0245")); }); + + it("Claim 50% - should revert if claimed twice for the same epoch", async function() { + const { sector3DAOPriority, owner, otherAccount, rewardToken } = await loadFixture(deployWeeklyFixture); + + await sector3DAOPriority.addContribution( + "Description #1", + "https://github.com/sector-3", + 5, + 60 + ); + + await sector3DAOPriority.connect(otherAccount).addContribution( + "Description #2", + "https://github.com/sector-3", + 5, + 60 + ); + + // Increase the time by 1 week + // console.log("Current time:", await time.latest()); + const ONE_WEEK_IN_SECONDS = 7 * 24 * 60 * 60; + await time.increase(ONE_WEEK_IN_SECONDS); + // console.log("Time 1 week later:", await time.latest()); + + // Transfer funding to the contract + await rewardToken.transfer(sector3DAOPriority.address, ethers.utils.parseUnits("2.049")); + expect(await rewardToken.balanceOf(sector3DAOPriority.address)).to.equal(ethers.utils.parseUnits("2.049")); + + // Claim reward (owner account) + await sector3DAOPriority.claimReward(0); + expect(await rewardToken.balanceOf(sector3DAOPriority.address)).to.equal(ethers.utils.parseUnits("1.0245")); + + // Claim reward twice (owner account) + await expect(sector3DAOPriority.claimReward(0)).to.be.revertedWithCustomError( + sector3DAOPriority, + "RewardAlreadyClaimed" + ); + expect(await rewardToken.balanceOf(sector3DAOPriority.address)).to.equal(ethers.utils.parseUnits("1.0245")); + }); + }); + + + describe("isRewardClaimed", async function() { + it("epochIndex[0] - 0 contributions", async function() { + const { sector3DAOPriority, owner } = await loadFixture(deployWeeklyFixture); + + // Increase the time by 1 week + const ONE_WEEK_IN_SECONDS = 7 * 24 * 60 * 60; + await time.increase(ONE_WEEK_IN_SECONDS); + + expect(await sector3DAOPriority.isRewardClaimed(0, owner.address)).to.equal(false); + }); + + it("epochIndex[0] - 0 claims", async function() { + const { sector3DAOPriority, owner } = await loadFixture(deployWeeklyFixture); + + await sector3DAOPriority.addContribution( + "Description", + "https://github.com/sector-3", + 8, + 80 + ); + + // Increase the time by 1 week + const ONE_WEEK_IN_SECONDS = 7 * 24 * 60 * 60; + await time.increase(ONE_WEEK_IN_SECONDS); + + expect(await sector3DAOPriority.isRewardClaimed(0, owner.address)).to.equal(false); + }); + + it("epochIndex[0] - 1 claim", async function() { + const { sector3DAOPriority, owner, rewardToken } = await loadFixture(deployWeeklyFixture); + + await sector3DAOPriority.addContribution( + "Description", + "https://github.com/sector-3", + 8, + 80 + ); + + // Increase the time by 1 week + const ONE_WEEK_IN_SECONDS = 7 * 24 * 60 * 60; + await time.increase(ONE_WEEK_IN_SECONDS); + + // Transfer funding to the contract + await rewardToken.transfer(sector3DAOPriority.address, ethers.utils.parseUnits("2.049")); + expect(await rewardToken.balanceOf(sector3DAOPriority.address)).to.equal(ethers.utils.parseUnits("2.049")); + + // Claim reward (owner account) + await sector3DAOPriority.claimReward(0); + + expect(await sector3DAOPriority.isRewardClaimed(0, owner.address)).to.equal(true); + }); + + it("epochIndex[1] - 0 claims", async function() { + const { sector3DAOPriority, owner, rewardToken } = await loadFixture(deployWeeklyFixture); + + await sector3DAOPriority.addContribution( + "Description", + "https://github.com/sector-3", + 8, + 80 + ); + + // Increase the time by 1 week + const ONE_WEEK_IN_SECONDS = 7 * 24 * 60 * 60; + await time.increase(ONE_WEEK_IN_SECONDS); + + // Transfer funding to the contract + await rewardToken.transfer(sector3DAOPriority.address, ethers.utils.parseUnits("2.049")); + expect(await rewardToken.balanceOf(sector3DAOPriority.address)).to.equal(ethers.utils.parseUnits("2.049")); + + // Claim reward (owner account) + await sector3DAOPriority.claimReward(0); + + expect(await sector3DAOPriority.isRewardClaimed(0, owner.address)).to.equal(true); + + await sector3DAOPriority.addContribution( + "Description", + "https://github.com/sector-3", + 8, + 80 + ); + + // Increase the time by 1 week + await time.increase(ONE_WEEK_IN_SECONDS); + + expect(await sector3DAOPriority.isRewardClaimed(1, owner.address)).to.equal(false); + }); + + it("epochIndex[0] - 1 claim by another account", async function() { + const { sector3DAOPriority, owner, otherAccount, rewardToken } = await loadFixture(deployWeeklyFixture); + + await sector3DAOPriority.connect(otherAccount).addContribution( + "Description", + "https://github.com/sector-3", + 8, + 80 + ); + + // Increase the time by 1 week + const ONE_WEEK_IN_SECONDS = 7 * 24 * 60 * 60; + await time.increase(ONE_WEEK_IN_SECONDS); + + // Transfer funding to the contract + await rewardToken.transfer(sector3DAOPriority.address, ethers.utils.parseUnits("2.049")); + expect(await rewardToken.balanceOf(sector3DAOPriority.address)).to.equal(ethers.utils.parseUnits("2.049")); + + // Claim reward (other account) + await sector3DAOPriority.connect(otherAccount).claimReward(0); + + expect(await sector3DAOPriority.isRewardClaimed(0, owner.address)).to.equal(false); + expect(await sector3DAOPriority.isRewardClaimed(0, otherAccount.address)).to.equal(true); + }); }); }); From 8f1c001e6caf4572f7f3b4993e86f53709c82c95 Mon Sep 17 00:00:00 2001 From: aahna-ashina <95955389+aahna-ashina@users.noreply.github.com> Date: Mon, 13 Mar 2023 11:16:26 +0800 Subject: [PATCH 10/17] feat: update dao owner (#47) closes #47 --- contracts/protocol/Sector3DAO.sol | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/contracts/protocol/Sector3DAO.sol b/contracts/protocol/Sector3DAO.sol index 10d0aff..4028c5a 100644 --- a/contracts/protocol/Sector3DAO.sol +++ b/contracts/protocol/Sector3DAO.sol @@ -46,6 +46,14 @@ contract Sector3DAO { owner = msg.sender; } + /** + * Updates the DAO's owner. + */ + function setOwner(address owner_) public { + require(msg.sender == owner, "You aren't the owner"); + owner = owner_; + } + /** * Updates the DAO's name. */ From bfcefc0d1debbe0b3d636d2273b2608cdc2481a5 Mon Sep 17 00:00:00 2001 From: aahna-ashina <95955389+aahna-ashina@users.noreply.github.com> Date: Mon, 13 Mar 2023 12:13:13 +0800 Subject: [PATCH 11/17] feat: calculate total funding amount of priority (#24) --- contracts/protocol/Sector3DAOPriority.sol | 19 +++++++++++ test/Sector3DAOFactory.ts | 2 +- ...ctor3Priority.ts => Sector3DAOPriority.ts} | 33 ++++++++++++++++++- 3 files changed, 52 insertions(+), 2 deletions(-) rename test/{Sector3Priority.ts => Sector3DAOPriority.ts} (95%) diff --git a/contracts/protocol/Sector3DAOPriority.sol b/contracts/protocol/Sector3DAOPriority.sol index 9d982da..0c4356e 100644 --- a/contracts/protocol/Sector3DAOPriority.sol +++ b/contracts/protocol/Sector3DAOPriority.sol @@ -18,11 +18,13 @@ contract Sector3DAOPriority is IPriority { IERC721 public immutable gatingNFT; Contribution[] contributions; mapping(uint16 => mapping(address => bool)) claims; + uint256 public claimsBalance; event ContributionAdded(Contribution contribution); event RewardClaimed(uint16 epochIndex, address contributor, uint256 amount); error EpochNotYetEnded(); + error EpochNotYetFunded(); error NoRewardForEpoch(); error RewardAlreadyClaimed(); error NoGatingNFTOwnership(); @@ -46,6 +48,9 @@ contract Sector3DAOPriority is IPriority { return uint16(timePassedSinceStart / epochDurationInSeconds); } + /** + * @notice Adds a contribution to the current epoch. + */ function addContribution(string memory description, string memory proofURL, uint8 hoursSpent, uint8 alignmentPercentage) public { if (address(gatingNFT) != address(0x0)) { if (gatingNFT.balanceOf(msg.sender) == 0) { @@ -78,6 +83,10 @@ contract Sector3DAOPriority is IPriority { if (epochIndex >= getEpochIndex()) { revert EpochNotYetEnded(); } + bool epochFunded = isEpochFunded(epochIndex); + if (!epochFunded) { + revert EpochNotYetFunded(); + } uint256 epochReward = getEpochReward(epochIndex, msg.sender); if (epochReward == 0) { revert NoRewardForEpoch(); @@ -88,6 +97,7 @@ contract Sector3DAOPriority is IPriority { } rewardToken.transfer(msg.sender, epochReward); claims[epochIndex][msg.sender] = true; + claimsBalance += epochReward; emit RewardClaimed(epochIndex, msg.sender, epochReward); } @@ -131,4 +141,13 @@ contract Sector3DAOPriority is IPriority { return uint8(hoursSpentContributor * 100 / hoursSpentAllContributors); } } + + /** + * @notice Checks if the smart contract has received enough funding to cover claims for a given epoch. + */ + function isEpochFunded(uint16 epochIndex) public view returns (bool) { + uint256 totalFundingAmount = rewardToken.balanceOf(address(this)) + claimsBalance; + uint256 totalBudgetAmount = epochBudget * (epochIndex + 1); + return totalFundingAmount >= totalBudgetAmount; + } } diff --git a/test/Sector3DAOFactory.ts b/test/Sector3DAOFactory.ts index 5898461..76efbd5 100644 --- a/test/Sector3DAOFactory.ts +++ b/test/Sector3DAOFactory.ts @@ -81,7 +81,7 @@ describe("Sector3DAOFactory", function () { await sector3DAOFactory.removeDAO(daos[0]); const daosAfterRemoval = await sector3DAOFactory.getDAOs(); - console.log('daosAfterRemoval:', daosAfterRemoval); + // console.log('daosAfterRemoval:', daosAfterRemoval); expect(daosAfterRemoval.length).to.equal(0); }) }); diff --git a/test/Sector3Priority.ts b/test/Sector3DAOPriority.ts similarity index 95% rename from test/Sector3Priority.ts rename to test/Sector3DAOPriority.ts index f08c1dc..f54a8c6 100644 --- a/test/Sector3Priority.ts +++ b/test/Sector3DAOPriority.ts @@ -597,8 +597,34 @@ describe("Sector3DAOPriority", function () { ); }); + it("Should revert if the epoch has not yet been funded", async function() { + const { sector3DAOPriority, owner, rewardToken } = await loadFixture(deployWeeklyFixture); + + // Increase the time by 1 week + const ONE_WEEK_IN_SECONDS = 7 * 24 * 60 * 60; + await time.increase(ONE_WEEK_IN_SECONDS); + + await expect(sector3DAOPriority.claimReward(0)).to.be.revertedWithCustomError( + sector3DAOPriority, + "EpochNotYetFunded" + ); + + // Increase the time by 1 week + await time.increase(ONE_WEEK_IN_SECONDS); + + // Transfer funding to the contract (for the first epoch) + await rewardToken.transfer(sector3DAOPriority.address, ethers.utils.parseUnits("2.049")); + expect(await rewardToken.balanceOf(sector3DAOPriority.address)).to.equal(ethers.utils.parseUnits("2.049")); + + await expect(sector3DAOPriority.claimReward(1)).to.be.revertedWithCustomError( + sector3DAOPriority, + "EpochNotYetFunded" + ); + expect(await rewardToken.balanceOf(sector3DAOPriority.address)).to.equal(ethers.utils.parseUnits("2.049")); + }); + it("Should revert if the account made no contributions during the epoch", async function() { - const { sector3DAOPriority, owner } = await loadFixture(deployWeeklyFixture); + const { sector3DAOPriority, owner, rewardToken } = await loadFixture(deployWeeklyFixture); // Increase the time by 1 week // console.log("Current time:", await time.latest()); @@ -606,10 +632,15 @@ describe("Sector3DAOPriority", function () { await time.increase(ONE_WEEK_IN_SECONDS); // console.log("Time 1 week later:", await time.latest()); + // Transfer funding to the contract + await rewardToken.transfer(sector3DAOPriority.address, ethers.utils.parseUnits("2.049")); + expect(await rewardToken.balanceOf(sector3DAOPriority.address)).to.equal(ethers.utils.parseUnits("2.049")); + await expect(sector3DAOPriority.claimReward(0)).to.be.revertedWithCustomError( sector3DAOPriority, "NoRewardForEpoch" ); + expect(await rewardToken.balanceOf(sector3DAOPriority.address)).to.equal(ethers.utils.parseUnits("2.049")); }); it("Claim 100%", async function() { From b61536650b3aaebfa4cf4a06708d4b855a41e4e8 Mon Sep 17 00:00:00 2001 From: aahna-ashina <95955389+aahna-ashina@users.noreply.github.com> Date: Mon, 13 Mar 2023 16:20:52 +0800 Subject: [PATCH 12/17] feat: handle epochs without contributions (#25) --- contracts/protocol/Sector3DAOPriority.sol | 51 ++- test/Sector3DAOFactory.ts | 2 +- test/Sector3DAOPriority.ts | 358 ++++++++++++++++++++++ 3 files changed, 402 insertions(+), 9 deletions(-) diff --git a/contracts/protocol/Sector3DAOPriority.sol b/contracts/protocol/Sector3DAOPriority.sol index 0c4356e..edb31cf 100644 --- a/contracts/protocol/Sector3DAOPriority.sol +++ b/contracts/protocol/Sector3DAOPriority.sol @@ -74,6 +74,24 @@ contract Sector3DAOPriority is IPriority { return contributions; } + function getEpochContributions(uint16 epochIndex) public view returns (Contribution[] memory) { + uint16 count = 0; + for (uint16 i = 0; i < contributions.length; i++) { + if (contributions[i].epochIndex == epochIndex) { + count++; + } + } + Contribution[] memory epochContributions = new Contribution[](count); + count = 0; + for (uint16 i = 0; i < contributions.length; i++) { + if (contributions[i].epochIndex == epochIndex) { + epochContributions[count] = contributions[i]; + count++; + } + } + return epochContributions; + } + /** * Claims a contributor's reward for contributions made in a given epoch. * @@ -83,14 +101,14 @@ contract Sector3DAOPriority is IPriority { if (epochIndex >= getEpochIndex()) { revert EpochNotYetEnded(); } - bool epochFunded = isEpochFunded(epochIndex); - if (!epochFunded) { - revert EpochNotYetFunded(); - } uint256 epochReward = getEpochReward(epochIndex, msg.sender); if (epochReward == 0) { revert NoRewardForEpoch(); } + bool epochFunded = isEpochFunded(epochIndex); + if (!epochFunded) { + revert EpochNotYetFunded(); + } bool rewardClaimed = isRewardClaimed(epochIndex, msg.sender); if (rewardClaimed) { revert RewardAlreadyClaimed(); @@ -143,11 +161,28 @@ contract Sector3DAOPriority is IPriority { } /** - * @notice Checks if the smart contract has received enough funding to cover claims for a given epoch. + * @notice Checks if the smart contract has received enough funding to cover claims for a past epoch. + * @dev Epochs without contributions are excluded from funding. */ function isEpochFunded(uint16 epochIndex) public view returns (bool) { - uint256 totalFundingAmount = rewardToken.balanceOf(address(this)) + claimsBalance; - uint256 totalBudgetAmount = epochBudget * (epochIndex + 1); - return totalFundingAmount >= totalBudgetAmount; + if (epochIndex >= getEpochIndex()) { + revert EpochNotYetEnded(); + } + if (getEpochContributions(epochIndex).length == 0) { + return false; + } + uint16 numberOfEpochsWithContributions = 0; + for (uint16 i = 0; i <= epochIndex; i++) { + if (getEpochContributions(i).length > 0) { + numberOfEpochsWithContributions++; + } + } + if (numberOfEpochsWithContributions == 0) { + return false; + } else { + uint256 totalBudget = epochBudget * numberOfEpochsWithContributions; + uint256 totalFundingReceived = rewardToken.balanceOf(address(this)) + claimsBalance; + return totalFundingReceived >= totalBudget; + } } } diff --git a/test/Sector3DAOFactory.ts b/test/Sector3DAOFactory.ts index 76efbd5..0e09fbf 100644 --- a/test/Sector3DAOFactory.ts +++ b/test/Sector3DAOFactory.ts @@ -62,7 +62,7 @@ describe("Sector3DAOFactory", function () { await sector3DAOFactory.removeDAO(daos[0]); const daosAfterRemoval = await sector3DAOFactory.getDAOs(); - console.log('daosAfterRemoval:', daosAfterRemoval); + // console.log('daosAfterRemoval:', daosAfterRemoval); expect(daosAfterRemoval.length).to.equal(1); expect(daosAfterRemoval[0]).to.equal(daos[1]); }) diff --git a/test/Sector3DAOPriority.ts b/test/Sector3DAOPriority.ts index f54a8c6..e7feef2 100644 --- a/test/Sector3DAOPriority.ts +++ b/test/Sector3DAOPriority.ts @@ -600,6 +600,13 @@ describe("Sector3DAOPriority", function () { it("Should revert if the epoch has not yet been funded", async function() { const { sector3DAOPriority, owner, rewardToken } = await loadFixture(deployWeeklyFixture); + await sector3DAOPriority.addContribution( + "Description #1", + "https://github.com/sector-3", + 5, + 60 + ); + // Increase the time by 1 week const ONE_WEEK_IN_SECONDS = 7 * 24 * 60 * 60; await time.increase(ONE_WEEK_IN_SECONDS); @@ -609,6 +616,13 @@ describe("Sector3DAOPriority", function () { "EpochNotYetFunded" ); + await sector3DAOPriority.addContribution( + "Description #2", + "https://github.com/sector-3", + 5, + 60 + ); + // Increase the time by 1 week await time.increase(ONE_WEEK_IN_SECONDS); @@ -616,6 +630,7 @@ describe("Sector3DAOPriority", function () { await rewardToken.transfer(sector3DAOPriority.address, ethers.utils.parseUnits("2.049")); expect(await rewardToken.balanceOf(sector3DAOPriority.address)).to.equal(ethers.utils.parseUnits("2.049")); + // Attempt to claim rewards for the second epoch await expect(sector3DAOPriority.claimReward(1)).to.be.revertedWithCustomError( sector3DAOPriority, "EpochNotYetFunded" @@ -860,4 +875,347 @@ describe("Sector3DAOPriority", function () { expect(await sector3DAOPriority.isRewardClaimed(0, otherAccount.address)).to.equal(true); }); }); + + + describe("isEpochFunded", async function() { + it("1st epoch without contributions", async function() { + const { sector3DAOPriority, owner, rewardToken } = await loadFixture(deployWeeklyFixture); + + // Increase the time by 1 week + const ONE_WEEK_IN_SECONDS = 7 * 24 * 60 * 60; + await time.increase(ONE_WEEK_IN_SECONDS); + + expect(await sector3DAOPriority.isEpochFunded(0)).to.equal(false); + + // Transfer funding to the contract + await rewardToken.transfer(sector3DAOPriority.address, ethers.utils.parseUnits("2.049")); + expect(await rewardToken.balanceOf(sector3DAOPriority.address)).to.equal(ethers.utils.parseUnits("2.049")); + + expect(await sector3DAOPriority.isEpochFunded(0)).to.equal(false); + }); + + it("1st and 2nd epoch without contributions", async function() { + const { sector3DAOPriority, owner, rewardToken } = await loadFixture(deployWeeklyFixture); + + // Increase the time by 1 week + const ONE_WEEK_IN_SECONDS = 7 * 24 * 60 * 60; + await time.increase(ONE_WEEK_IN_SECONDS); + + expect(await sector3DAOPriority.isEpochFunded(0)).to.equal(false); + + // Increase the time by 1 week + await time.increase(ONE_WEEK_IN_SECONDS); + + expect(await sector3DAOPriority.isEpochFunded(0)).to.equal(false); + expect(await sector3DAOPriority.isEpochFunded(1)).to.equal(false); + + // Transfer funding to the contract + await rewardToken.transfer(sector3DAOPriority.address, ethers.utils.parseUnits("2.049")); + expect(await rewardToken.balanceOf(sector3DAOPriority.address)).to.equal(ethers.utils.parseUnits("2.049")); + + expect(await sector3DAOPriority.isEpochFunded(0)).to.equal(false); + expect(await sector3DAOPriority.isEpochFunded(1)).to.equal(false); + }); + + it("1st epoch with contributions, 2nd epoch without contributions", async function() { + const { sector3DAOPriority, owner, rewardToken } = await loadFixture(deployWeeklyFixture); + + await sector3DAOPriority.addContribution( + "Description", + "https://github.com/sector-3", + 8, + 80 + ); + + // Increase the time by 1 week + const ONE_WEEK_IN_SECONDS = 7 * 24 * 60 * 60; + await time.increase(ONE_WEEK_IN_SECONDS); + + expect(await sector3DAOPriority.isEpochFunded(0)).to.equal(false); + + // Increase the time by 1 week + await time.increase(ONE_WEEK_IN_SECONDS); + + expect(await sector3DAOPriority.isEpochFunded(0)).to.equal(false); + expect(await sector3DAOPriority.isEpochFunded(1)).to.equal(false); + + // Transfer funding to the contract + await rewardToken.transfer(sector3DAOPriority.address, ethers.utils.parseUnits("2.049")); + expect(await rewardToken.balanceOf(sector3DAOPriority.address)).to.equal(ethers.utils.parseUnits("2.049")); + + expect(await sector3DAOPriority.isEpochFunded(0)).to.equal(true); + expect(await sector3DAOPriority.isEpochFunded(1)).to.equal(false); + + // Transfer funding to the contract + await rewardToken.transfer(sector3DAOPriority.address, ethers.utils.parseUnits("2.049")); + expect(await rewardToken.balanceOf(sector3DAOPriority.address)).to.equal(ethers.utils.parseUnits("4.098")); + + expect(await sector3DAOPriority.isEpochFunded(0)).to.equal(true); + expect(await sector3DAOPriority.isEpochFunded(1)).to.equal(false); + }); + + it("1st epoch with contributions, 2nd with contributions", async function() { + const { sector3DAOPriority, owner, rewardToken } = await loadFixture(deployWeeklyFixture); + + await sector3DAOPriority.addContribution( + "Description", + "https://github.com/sector-3", + 8, + 80 + ); + + // Increase the time by 1 week + const ONE_WEEK_IN_SECONDS = 7 * 24 * 60 * 60; + await time.increase(ONE_WEEK_IN_SECONDS); + + expect(await sector3DAOPriority.isEpochFunded(0)).to.equal(false); + + await sector3DAOPriority.addContribution( + "Description", + "https://github.com/sector-3", + 8, + 80 + ); + + // Increase the time by 1 week + await time.increase(ONE_WEEK_IN_SECONDS); + + expect(await sector3DAOPriority.isEpochFunded(0)).to.equal(false); + expect(await sector3DAOPriority.isEpochFunded(1)).to.equal(false); + + // Transfer funding to the contract + await rewardToken.transfer(sector3DAOPriority.address, ethers.utils.parseUnits("2.049")); + expect(await rewardToken.balanceOf(sector3DAOPriority.address)).to.equal(ethers.utils.parseUnits("2.049")); + + expect(await sector3DAOPriority.isEpochFunded(0)).to.equal(true); + expect(await sector3DAOPriority.isEpochFunded(1)).to.equal(false); + + // Transfer funding to the contract + await rewardToken.transfer(sector3DAOPriority.address, ethers.utils.parseUnits("2.049")); + expect(await rewardToken.balanceOf(sector3DAOPriority.address)).to.equal(ethers.utils.parseUnits("4.098")); + + expect(await sector3DAOPriority.isEpochFunded(0)).to.equal(true); + expect(await sector3DAOPriority.isEpochFunded(1)).to.equal(true); + }); + + it("1st epoch without contributions, 2nd with contributions", async function() { + const { sector3DAOPriority, owner, rewardToken } = await loadFixture(deployWeeklyFixture); + + // Increase the time by 1 week + const ONE_WEEK_IN_SECONDS = 7 * 24 * 60 * 60; + await time.increase(ONE_WEEK_IN_SECONDS); + + expect(await sector3DAOPriority.isEpochFunded(0)).to.equal(false); + + await sector3DAOPriority.addContribution( + "Description", + "https://github.com/sector-3", + 8, + 80 + ); + + // Increase the time by 1 week + await time.increase(ONE_WEEK_IN_SECONDS); + + expect(await sector3DAOPriority.isEpochFunded(0)).to.equal(false); + expect(await sector3DAOPriority.isEpochFunded(1)).to.equal(false); + + // Transfer funding to the contract + await rewardToken.transfer(sector3DAOPriority.address, ethers.utils.parseUnits("2.049")); + expect(await rewardToken.balanceOf(sector3DAOPriority.address)).to.equal(ethers.utils.parseUnits("2.049")); + + expect(await sector3DAOPriority.isEpochFunded(0)).to.equal(false); + expect(await sector3DAOPriority.isEpochFunded(1)).to.equal(true); + + // Transfer funding to the contract + await rewardToken.transfer(sector3DAOPriority.address, ethers.utils.parseUnits("2.049")); + expect(await rewardToken.balanceOf(sector3DAOPriority.address)).to.equal(ethers.utils.parseUnits("4.098")); + + expect(await sector3DAOPriority.isEpochFunded(0)).to.equal(false); + expect(await sector3DAOPriority.isEpochFunded(1)).to.equal(true); + }); + + it("pre-funded - 1st epoch without contributions, 2nd with contributions", async function() { + const { sector3DAOPriority, owner, rewardToken } = await loadFixture(deployWeeklyFixture); + + // Transfer funding to the contract + await rewardToken.transfer(sector3DAOPriority.address, ethers.utils.parseUnits("4.098")); + expect(await rewardToken.balanceOf(sector3DAOPriority.address)).to.equal(ethers.utils.parseUnits("4.098")); + + // Increase the time by 1 week + const ONE_WEEK_IN_SECONDS = 7 * 24 * 60 * 60; + await time.increase(ONE_WEEK_IN_SECONDS); + + expect(await sector3DAOPriority.isEpochFunded(0)).to.equal(false); + + await sector3DAOPriority.addContribution( + "Description", + "https://github.com/sector-3", + 8, + 80 + ); + + // Increase the time by 1 week + await time.increase(ONE_WEEK_IN_SECONDS); + + expect(await sector3DAOPriority.isEpochFunded(0)).to.equal(false); + expect(await sector3DAOPriority.isEpochFunded(1)).to.equal(true); + }); + + it("1st epoch - edge cases", async function() { + const { sector3DAOPriority, owner, rewardToken } = await loadFixture(deployWeeklyFixture); + + await sector3DAOPriority.addContribution( + "Description", + "https://github.com/sector-3", + 8, + 80 + ); + + // Increase the time by 1 week + const ONE_WEEK_IN_SECONDS = 7 * 24 * 60 * 60; + await time.increase(ONE_WEEK_IN_SECONDS); + + // Transfer funding to the contract + await rewardToken.transfer(sector3DAOPriority.address, ethers.utils.parseUnits("2.048")); + expect(await rewardToken.balanceOf(sector3DAOPriority.address)).to.equal(ethers.utils.parseUnits("2.048")); + + expect(await sector3DAOPriority.isEpochFunded(0)).to.equal(false); + + // Transfer funding to the contract + await rewardToken.transfer(sector3DAOPriority.address, ethers.utils.parseUnits("0.001")); + expect(await rewardToken.balanceOf(sector3DAOPriority.address)).to.equal(ethers.utils.parseUnits("2.049")); + + expect(await sector3DAOPriority.isEpochFunded(0)).to.equal(true); + + // Transfer funding to the contract + await rewardToken.transfer(sector3DAOPriority.address, ethers.utils.parseUnits("0.001")); + expect(await rewardToken.balanceOf(sector3DAOPriority.address)).to.equal(ethers.utils.parseUnits("2.050")); + + expect(await sector3DAOPriority.isEpochFunded(0)).to.equal(true); + }); + + it("2nd epoch - edge cases", async function() { + const { sector3DAOPriority, owner, rewardToken } = await loadFixture(deployWeeklyFixture); + + await sector3DAOPriority.addContribution( + "Description", + "https://github.com/sector-3", + 8, + 80 + ); + + // Increase the time by 1 week + const ONE_WEEK_IN_SECONDS = 7 * 24 * 60 * 60; + await time.increase(ONE_WEEK_IN_SECONDS); + + await sector3DAOPriority.addContribution( + "Description", + "https://github.com/sector-3", + 8, + 80 + ); + + // Increase the time by 1 week + await time.increase(ONE_WEEK_IN_SECONDS); + + // Transfer funding to the contract + await rewardToken.transfer(sector3DAOPriority.address, ethers.utils.parseUnits("2.048")); + expect(await rewardToken.balanceOf(sector3DAOPriority.address)).to.equal(ethers.utils.parseUnits("2.048")); + + expect(await sector3DAOPriority.isEpochFunded(0)).to.equal(false); + expect(await sector3DAOPriority.isEpochFunded(1)).to.equal(false); + + // Transfer funding to the contract + await rewardToken.transfer(sector3DAOPriority.address, ethers.utils.parseUnits("0.001")); + expect(await rewardToken.balanceOf(sector3DAOPriority.address)).to.equal(ethers.utils.parseUnits("2.049")); + + expect(await sector3DAOPriority.isEpochFunded(0)).to.equal(true); + expect(await sector3DAOPriority.isEpochFunded(1)).to.equal(false); + + // Transfer funding to the contract + await rewardToken.transfer(sector3DAOPriority.address, ethers.utils.parseUnits("0.001")); + expect(await rewardToken.balanceOf(sector3DAOPriority.address)).to.equal(ethers.utils.parseUnits("2.050")); + + expect(await sector3DAOPriority.isEpochFunded(0)).to.equal(true); + expect(await sector3DAOPriority.isEpochFunded(1)).to.equal(false); + + // Transfer funding to the contract + await rewardToken.transfer(sector3DAOPriority.address, ethers.utils.parseUnits("2.047")); + expect(await rewardToken.balanceOf(sector3DAOPriority.address)).to.equal(ethers.utils.parseUnits("4.097")); + + expect(await sector3DAOPriority.isEpochFunded(0)).to.equal(true); + expect(await sector3DAOPriority.isEpochFunded(1)).to.equal(false); + + // Transfer funding to the contract + await rewardToken.transfer(sector3DAOPriority.address, ethers.utils.parseUnits("0.001")); + expect(await rewardToken.balanceOf(sector3DAOPriority.address)).to.equal(ethers.utils.parseUnits("4.098")); + + expect(await sector3DAOPriority.isEpochFunded(0)).to.equal(true); + expect(await sector3DAOPriority.isEpochFunded(1)).to.equal(true); + }); + }); + + it("1st epoch with contributions, after 100% claimed", async function() { + const { sector3DAOPriority, owner, rewardToken } = await loadFixture(deployWeeklyFixture); + + await sector3DAOPriority.addContribution( + "Description", + "https://github.com/sector-3", + 8, + 80 + ); + + // Increase the time by 1 week + const ONE_WEEK_IN_SECONDS = 7 * 24 * 60 * 60; + await time.increase(ONE_WEEK_IN_SECONDS); + + // Transfer funding to the contract + await rewardToken.transfer(sector3DAOPriority.address, ethers.utils.parseUnits("2.049")); + expect(await rewardToken.balanceOf(sector3DAOPriority.address)).to.equal(ethers.utils.parseUnits("2.049")); + + expect(await sector3DAOPriority.isEpochFunded(0)).to.equal(true); + expect(await sector3DAOPriority.claimsBalance()).to.equal(0); + + await sector3DAOPriority.claimReward(0); + + expect(await sector3DAOPriority.isEpochFunded(0)).to.equal(true); + expect(await rewardToken.balanceOf(sector3DAOPriority.address)).to.equal(0); + expect(await sector3DAOPriority.claimsBalance()).to.equal(ethers.utils.parseUnits("2.049")); + }); + + it("1st epoch with contributions, after 50% claimed", async function() { + const { sector3DAOPriority, owner, otherAccount, rewardToken } = await loadFixture(deployWeeklyFixture); + + await sector3DAOPriority.addContribution( + "Description", + "https://github.com/sector-3", + 8, + 80 + ); + + await sector3DAOPriority.connect(otherAccount).addContribution( + "Description (other account)", + "https://github.com/sector-3", + 8, + 80 + ); + + // Increase the time by 1 week + const ONE_WEEK_IN_SECONDS = 7 * 24 * 60 * 60; + await time.increase(ONE_WEEK_IN_SECONDS); + + // Transfer funding to the contract + await rewardToken.transfer(sector3DAOPriority.address, ethers.utils.parseUnits("2.049")); + expect(await rewardToken.balanceOf(sector3DAOPriority.address)).to.equal(ethers.utils.parseUnits("2.049")); + + expect(await sector3DAOPriority.isEpochFunded(0)).to.equal(true); + expect(await sector3DAOPriority.claimsBalance()).to.equal(0); + + await sector3DAOPriority.claimReward(0); + + expect(await sector3DAOPriority.isEpochFunded(0)).to.equal(true); + expect(await rewardToken.balanceOf(sector3DAOPriority.address)).to.equal(ethers.utils.parseUnits("1.0245")); + expect(await sector3DAOPriority.claimsBalance()).to.equal(ethers.utils.parseUnits("1.0245")); + }); }); From b03e3fde469fd85b622e6cbd5a8071b93229bff0 Mon Sep 17 00:00:00 2001 From: aahna-ashina <95955389+aahna-ashina@users.noreply.github.com> Date: Mon, 13 Mar 2023 16:41:47 +0800 Subject: [PATCH 13/17] chore: add sepolia testnet (#57) --- README.md | 4 ++-- contracts/protocol/Sector3DAOFactory.sol | 4 ---- hardhat.config.ts | 5 +++++ package-lock.json | 4 ++-- package.json | 2 +- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 66c0620..70f8c99 100644 --- a/README.md +++ b/README.md @@ -43,10 +43,10 @@ Deploy a smart contract to the local network: npx hardhat run --network localhost scripts/deploy-.ts ``` -Deploy a smart contract to the Goerli test network: +Deploy a smart contract to the Sepolia test network: ```shell -npx hardhat run --network goerli scripts/deploy-.ts +npx hardhat run --network sepolia scripts/deploy-.ts ``` Verify a contract on Etherscan: diff --git a/contracts/protocol/Sector3DAOFactory.sol b/contracts/protocol/Sector3DAOFactory.sol index 529fd63..df77333 100644 --- a/contracts/protocol/Sector3DAOFactory.sol +++ b/contracts/protocol/Sector3DAOFactory.sol @@ -11,10 +11,6 @@ contract Sector3DAOFactory { constructor() { owner = msg.sender; - // // daos.push(0x5FbDB2315678afecb367f032d93F642f64180aa3); // localhost - // daos.push(0xEa98D59e4EF83822393AF87e587713c2674eD4FD); // Sector#3 DAO (v0) - // daos.push(0x2D624a0bA38b40B4f7bE2bfeb56B6B0dD81Be6A1); // Nation3 (v0) - // daos.push(0x9741B82017485759c9Bcc13FeA10c1105f82d25C); // Bankless Africa (v0) } function setOwner(address owner_) public { diff --git a/hardhat.config.ts b/hardhat.config.ts index 479c0cb..0fa6627 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -18,6 +18,10 @@ const config: HardhatUserConfig = { url: "https://rpc.ankr.com/eth_goerli", accounts: [ String(process.env.DEPLOYER_PRIVATE_KEY) ] }, + sepolia: { + url: "https://rpc.ankr.com/eth_sepolia", + accounts: [ String(process.env.DEPLOYER_PRIVATE_KEY) ] + }, mainnet: { url: "https://rpc.ankr.com/eth", accounts: [ String(process.env.DEPLOYER_PRIVATE_KEY) ] @@ -26,6 +30,7 @@ const config: HardhatUserConfig = { etherscan: { apiKey: { goerli: String(process.env.ETHERSCAN_API_KEY), + sepolia: String(process.env.ETHERSCAN_API_KEY), mainnet: String(process.env.ETHERSCAN_API_KEY) } } diff --git a/package-lock.json b/package-lock.json index 68858ac..4e9e4a9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "section3-contracts", - "version": "1.0.1", + "version": "1.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "section3-contracts", - "version": "1.0.1", + "version": "1.1.0", "license": "MIT", "devDependencies": { "@nomicfoundation/hardhat-toolbox": "^2.0.2", diff --git a/package.json b/package.json index 3133cbf..8ab330f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "section3-contracts", - "version": "1.0.1", + "version": "1.1.0", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, From 66044a99c2e2de2c4e80ebcd1f65d41044fdc85b Mon Sep 17 00:00:00 2001 From: Aahna Ashina <95955389+aahna-ashina@users.noreply.github.com> Date: Tue, 14 Mar 2023 11:18:42 +0800 Subject: [PATCH 14/17] Update pull_request_template.md --- .github/pull_request_template.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 2d2a48a..9b426c6 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -8,6 +8,6 @@ ## Sector#3 Contribution - + -- [ ] Reported contribution at https://goerli.sector3.xyz/v0/priorities/0x6660626F3b51c0A7a9C558Ade45B17B7De6f91c1 +- [ ] Reported contribution at https://sepolia.sector3.xyz/v1/daos/0xB1932B5ba9Dfd0a2dCFa08140eb272DC60804699 From 3c722fa86e8e9df8c5ccafca042e36495046ed88 Mon Sep 17 00:00:00 2001 From: aahna-ashina <95955389+aahna-ashina@users.noreply.github.com> Date: Tue, 14 Mar 2023 11:25:11 +0800 Subject: [PATCH 15/17] fix: set dao owner (#47) --- contracts/protocol/Sector3DAO.sol | 2 +- test/Sector3DAOFactory.ts | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/contracts/protocol/Sector3DAO.sol b/contracts/protocol/Sector3DAO.sol index 4028c5a..316ff31 100644 --- a/contracts/protocol/Sector3DAO.sol +++ b/contracts/protocol/Sector3DAO.sol @@ -43,7 +43,7 @@ contract Sector3DAO { name = name_; purpose = purpose_; token = token_; - owner = msg.sender; + owner = tx.origin; } /** diff --git a/test/Sector3DAOFactory.ts b/test/Sector3DAOFactory.ts index 0e09fbf..96da86b 100644 --- a/test/Sector3DAOFactory.ts +++ b/test/Sector3DAOFactory.ts @@ -29,7 +29,7 @@ describe("Sector3DAOFactory", function () { describe("DAOs", function () { it("deploy DAO", async function () { - const { sector3DAOFactory } = await loadFixture(deployFixture); + const { sector3DAOFactory, owner } = await loadFixture(deployFixture); let daos = await sector3DAOFactory.getDAOs(); // console.log('daos:', daos); @@ -37,9 +37,13 @@ describe("Sector3DAOFactory", function () { await sector3DAOFactory.deployDAO("DAO #1", "Purpose #1", "0x610210AA5D51bf26CBce146A5992D2FEeBc27dB1"); daos = await sector3DAOFactory.getDAOs(); - // console.log('daos:', daos); + console.log('daos:', daos); expect(daos.length).to.equal(1); + const Sector3DAO = await ethers.getContractFactory("Sector3DAO"); + const sector3DAO = await Sector3DAO.attach(daos[0]); + expect(await sector3DAO.owner()).to.equal(owner.address); + await sector3DAOFactory.deployDAO("DAO #2", "Purpose #2", "0x610210AA5D51bf26CBce146A5992D2FEeBc27dB1"); daos = await sector3DAOFactory.getDAOs(); // console.log('daos:', daos); From 81dc34d78d0697eedf204de088d9ddc15b1b08f4 Mon Sep 17 00:00:00 2001 From: aahna-ashina <95955389+aahna-ashina@users.noreply.github.com> Date: Tue, 14 Mar 2023 16:04:07 +0800 Subject: [PATCH 16/17] rename nft --- contracts/token/{Sector3Dove.sol => S3DOVE.sol} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename contracts/token/{Sector3Dove.sol => S3DOVE.sol} (100%) diff --git a/contracts/token/Sector3Dove.sol b/contracts/token/S3DOVE.sol similarity index 100% rename from contracts/token/Sector3Dove.sol rename to contracts/token/S3DOVE.sol From 4262063c9c82cae938609230472fc251e6bfff98 Mon Sep 17 00:00:00 2001 From: aahna-ashina <95955389+aahna-ashina@users.noreply.github.com> Date: Tue, 14 Mar 2023 16:07:37 +0800 Subject: [PATCH 17/17] rename nft --- contracts/token/S3DOVE.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/token/S3DOVE.sol b/contracts/token/S3DOVE.sol index d12ab90..9129742 100644 --- a/contracts/token/S3DOVE.sol +++ b/contracts/token/S3DOVE.sol @@ -6,7 +6,7 @@ import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/utils/Counters.sol"; -contract Sector3Dove is ERC721, ERC721Enumerable, Ownable { +contract S3DOVE is ERC721, ERC721Enumerable, Ownable { using Counters for Counters.Counter; Counters.Counter private _tokenIdCounter;