Skip to content

Commit

Permalink
feat(protocol):
Browse files Browse the repository at this point in the history
  • Loading branch information
developerfred committed Mar 15, 2023
1 parent 4262063 commit 4d0ecd3
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 18 deletions.
9 changes: 6 additions & 3 deletions contracts/protocol/Sector3DAO.sol
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,13 @@ contract Sector3DAO {
*/
Sector3DAOPriority[] public priorities;

event PriorityDeployed(Sector3DAOPriority priority);

constructor(string memory name_, string memory purpose_, address token_) {
name = name_;
purpose = purpose_;
token = token_;
owner = tx.origin;
owner = msg.sender;
}

/**
Expand Down Expand Up @@ -78,10 +80,11 @@ contract Sector3DAO {
token = token_;
}

function deployPriority(string calldata title, address rewardToken, uint16 epochDurationInDays, uint256 epochBudget, address gatingNFT) public returns (Sector3DAOPriority) {
function deployPriority(string calldata title, address rewardToken, uint16 epochDurationInDays, uint256 epochBudget, address gatingNFT, uint16 coolingWindowDurationInDays) public returns (Sector3DAOPriority) {
require(msg.sender == owner, "You aren't the owner");
Sector3DAOPriority priority = new Sector3DAOPriority(address(this), title, rewardToken, epochDurationInDays, epochBudget, gatingNFT);
Sector3DAOPriority priority = new Sector3DAOPriority(address(this), title, rewardToken, epochDurationInDays, epochBudget, gatingNFT, coolingWindowDurationInDays);
priorities.push(priority);
emit PriorityDeployed(priority);
return priority;
}

Expand Down
33 changes: 19 additions & 14 deletions contracts/protocol/Sector3DAOFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,40 +5,45 @@ import './Sector3DAO.sol';

contract Sector3DAOFactory {

address public owner;
address public immutable owner;

address[] public daos;

event DAODeployed(address dao);

constructor() {
owner = msg.sender;
}

function setOwner(address owner_) public {
modifier onlyOwner() {
require(msg.sender == owner, "You aren't the owner");
owner = owner_;
_;
}

function getDAOs() public view returns (address[] memory) {
return daos;
}

function deployDAO(string calldata name, string calldata purpose, address token) public returns (address) {
function deployDAO(string calldata name, string calldata purpose, address token) public returns (address) {
Sector3DAO dao = new Sector3DAO(name, purpose, token);
daos.push(address(dao));
return address(dao);
}

function removeDAO(address dao) public {
require(msg.sender == owner, "You aren't the owner");
address[] memory daosAfterRemoval = new address[](daos.length - 1);
uint16 daosIndex = 0;
for (uint16 i = 0; i < daosAfterRemoval.length; i++) {
if (dao == daos[daosIndex]) {
daosIndex++;
function removeDAO(address dao) public onlyOwner {
uint256 indexToRemove = daos.length;

for (uint256 i = 0; i < daos.length; i++) {
if (dao == daos[i]) {
indexToRemove = i;
break;
}
daosAfterRemoval[i] = daos[daosIndex];
daosIndex++;
}
daos = daosAfterRemoval;

require(indexToRemove < daos.length, "DAO not found");

// Use the "delete-and-swap" technique to save gas.
daos[indexToRemove] = daos[daos.length - 1];
daos.pop();
}
}
78 changes: 77 additions & 1 deletion contracts/protocol/Sector3DAOPriority.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ import "./Structs.sol";
contract Sector3DAOPriority is IPriority {
using SafeERC20 for IERC20;


struct Rating {
uint16 contributionIndex;
address rater;
uint8 rating;
}

address public immutable dao;
string public title;
IERC20 public immutable rewardToken;
Expand All @@ -17,26 +24,32 @@ contract Sector3DAOPriority is IPriority {
uint256 public immutable epochBudget;
IERC721 public immutable gatingNFT;
Contribution[] contributions;
Rating[] ratings;
mapping(uint16 => mapping(address => bool)) claims;
uint256 public claimsBalance;
uint16 public immutable coolingWindowDuration;

event ContributionAdded(Contribution contribution);
event RewardClaimed(uint16 epochIndex, address contributor, uint256 amount);
event ContributionRated(uint16 contributionIndex, address rater, uint8 rating);
event RatingUpdated(uint16 contributionIndex, address rater, uint8 newRating);

error EpochNotYetEnded();
error EpochNotYetFunded();
error NoRewardForEpoch();
error RewardAlreadyClaimed();
error NoGatingNFTOwnership();
error CoolingWindowNotEnded();

constructor(address dao_, string memory title_, address rewardToken_, uint16 epochDurationInDays, uint256 epochBudget_, address gatingNFT_) {
constructor(address dao_, string memory title_, address rewardToken_, uint16 epochDurationInDays, uint256 epochBudget_, address gatingNFT_, uint16 coolingWindowDurationInDays) {
dao = dao_;
title = title_;
rewardToken = IERC20(rewardToken_);
startTime = block.timestamp;
epochDuration = epochDurationInDays;
epochBudget = epochBudget_;
gatingNFT = IERC721(gatingNFT_);
coolingWindowDuration = coolingWindowDurationInDays;
}

/**
Expand Down Expand Up @@ -101,6 +114,9 @@ contract Sector3DAOPriority is IPriority {
if (epochIndex >= getEpochIndex()) {
revert EpochNotYetEnded();
}
if (block.timestamp < getCoolingWindowEndTime(epochIndex)) {
revert CoolingWindowNotEnded();
}
uint256 epochReward = getEpochReward(epochIndex, msg.sender);
if (epochReward == 0) {
revert NoRewardForEpoch();
Expand Down Expand Up @@ -185,4 +201,64 @@ contract Sector3DAOPriority is IPriority {
return totalFundingReceived >= totalBudget;
}
}

function rateContribution(uint16 contributionIndex, uint8 rating) public {
require(contributionIndex < contributions.length, "Invalid contribution index");
require(rating >= 1 && rating <= 5, "Invalid rating value");

uint16 ratingIndex = findRatingIndex(contributionIndex, msg.sender);

if (ratingIndex < ratings.length) {
ratings[ratingIndex].rating = rating;
emit RatingUpdated(contributionIndex, msg.sender, rating);
} else {
Rating memory newRating = Rating({
contributionIndex: contributionIndex,
rater: msg.sender,
rating: rating
});
ratings.push(newRating);
emit ContributionRated(contributionIndex, msg.sender, rating);
}
}

function findRatingIndex(uint16 contributionIndex, address rater) internal view returns (uint16) {
for (uint16 i = 0; i < ratings.length; i++) {
if (ratings[i].contributionIndex == contributionIndex && ratings[i].rater == rater) {
return i;
}
}
return uint16(ratings.length);
}

function getContributionRating(uint16 contributionIndex) public view returns (uint8) {
require(contributionIndex < contributions.length, "Invalid contribution index");

uint16 totalRatings = 0;
uint16 sumRatings = 0;

for (uint16 i = 0; i < ratings.length; i++) {
if (ratings[i].contributionIndex == contributionIndex) {
totalRatings++;
sumRatings += ratings[i].rating;
}
}

if (totalRatings == 0) {
return 0;
} else {
return uint8(sumRatings / totalRatings);
}
}

/**
* @notice Gets the end time of the cooling window for an epoch.
* @dev This should be implemented based on the requirements of the DAO.
* @param epochIndex The index of the epoch.
*/
function getCoolingWindowEndTime(uint16 epochIndex) public view returns (uint256) {
uint256 epochEndTime = startTime + (epochIndex + 1) * epochDuration * 1 days;
uint256 localCoolingWindowDuration = 3 * 1 days;
return epochEndTime + localCoolingWindowDuration;
}
}

0 comments on commit 4d0ecd3

Please sign in to comment.