Skip to content

Commit 8431c80

Browse files
committed
chore(contracts): fixed critical security issues
1 parent 61f467a commit 8431c80

File tree

3 files changed

+63
-14
lines changed

3 files changed

+63
-14
lines changed

contracts/protocol/Sector3DAO.sol

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,32 +46,34 @@ contract Sector3DAO {
4646
owner = msg.sender;
4747
}
4848

49+
modifier onlyOwner() {
50+
require(msg.sender == owner, "You are not authorized to perform this action.");
51+
_;
52+
}
53+
54+
4955
/**
5056
* Updates the DAO's name.
5157
*/
52-
function setName(string calldata name_) public {
53-
require(msg.sender == owner, "You aren't the owner");
58+
function setName(string calldata name_) public onlyOwner {
5459
name = name_;
5560
}
5661

5762
/**
5863
* Updates the DAO's purpose.
5964
*/
60-
function setPurpose(string calldata purpose_) public {
61-
require(msg.sender == owner, "You aren't the owner");
65+
function setPurpose(string calldata purpose_) public onlyOwner {
6266
purpose = purpose_;
6367
}
6468

6569
/**
6670
* Updates the DAO's token.
6771
*/
68-
function setToken(address token_) public {
69-
require(msg.sender == owner, "You aren't the owner");
72+
function setToken(address token_) public onlyOwner {
7073
token = token_;
7174
}
7275

73-
function deployPriority(string calldata title, address rewardToken, uint16 epochDurationInDays, uint256 epochBudget) public returns (Sector3DAOPriority) {
74-
require(msg.sender == owner, "You aren't the owner");
76+
function deployPriority(string calldata title, address rewardToken, uint16 epochDurationInDays, uint256 epochBudget) public onlyOwner returns (Sector3DAOPriority) {
7577
Sector3DAOPriority priority = new Sector3DAOPriority(address(this), title, rewardToken, epochDurationInDays, epochBudget);
7678
priorities.push(priority);
7779
return priority;
@@ -85,8 +87,8 @@ contract Sector3DAO {
8587
return priorities;
8688
}
8789

88-
function removePriority(Sector3DAOPriority priority) public {
89-
require(msg.sender == owner, "You aren't the owner");
90+
function removePriority(Sector3DAOPriority priority) public onlyOwner {
91+
require(!priority.isInVotingPeriod(), "Cannot remove priority during voting period");
9092
Sector3DAOPriority[] memory prioritiesAfterRemoval = new Sector3DAOPriority[](priorities.length - 1);
9193
uint16 prioritiesIndex = 0;
9294
for (uint16 i = 0; i < prioritiesAfterRemoval.length; i++) {
@@ -98,4 +100,6 @@ contract Sector3DAO {
98100
}
99101
priorities = prioritiesAfterRemoval;
100102
}
103+
104+
101105
}

contracts/protocol/Sector3DAOFactory.sol

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ contract Sector3DAOFactory {
99

1010
address[] public daos;
1111

12+
error YouAreNotAuthorized();
13+
1214
constructor() {
1315
owner = msg.sender;
1416
// daos.push(0x5FbDB2315678afecb367f032d93F642f64180aa3); // localhost
@@ -18,7 +20,15 @@ contract Sector3DAOFactory {
1820
daos.push(0x9741B82017485759c9Bcc13FeA10c1105f82d25C); // Bankless Africa (v0)
1921
}
2022

21-
function setOwner(address owner_) public {
23+
24+
25+
modifier onlyOwner() {
26+
require(msg.sender == owner, "You are not authorized to perform this action.");
27+
_;
28+
}
29+
30+
31+
function setOwner(address owner_) public onlyOwner {
2232
require(msg.sender == owner, "You aren't the owner");
2333
owner = owner_;
2434
}
@@ -33,7 +43,7 @@ contract Sector3DAOFactory {
3343
return address(dao);
3444
}
3545

36-
function removeDAO(address dao) public {
46+
function removeDAO(address dao) public onlyOwner {
3747
require(msg.sender == owner, "You aren't the owner");
3848
address[] memory daosAfterRemoval = new address[](daos.length - 1);
3949
uint16 daosIndex = 0;

contracts/protocol/Sector3DAOPriority.sol

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,19 @@ contract Sector3DAOPriority is IPriority {
9090
if (epochReward == 0) {
9191
revert NoRewardForEpoch();
9292
}
93-
rewardToken.transfer(msg.sender, epochReward);
93+
bool epochFunded = isEpochFunded(epochIndex);
94+
if (!epochFunded) {
95+
revert EpochNotYetFunded();
96+
}
97+
bool rewardClaimed = isRewardClaimed(epochIndex, msg.sender);
98+
if (rewardClaimed) {
99+
revert RewardAlreadyClaimed();
100+
}
101+
claims[epochIndex][msg.sender] = true;
102+
claimsBalance += epochReward;
103+
require(rewardToken.transfer(msg.sender, epochReward), "Reward transfer failed");
94104
emit RewardClaimed(epochIndex, msg.sender, epochReward);
95-
}
105+
}
96106

97107
/**
98108
* Calculates a contributor's token allocation of the budget for a given epoch.
@@ -104,6 +114,31 @@ contract Sector3DAOPriority is IPriority {
104114
return epochBudget * allocationPercentage / 100;
105115
}
106116

117+
/**
118+
* @notice Checks if the smart contract has received enough funding to cover claims for a past epoch.
119+
*
120+
* @param epochIndex The index of the epoch to check.
121+
* @return A boolean indicating whether the epoch is funded or not.
122+
*
123+
* @dev This function loops through all past epochs to calculate whether the current epoch is funded or not.
124+
* If the number of past epochs becomes very large, the function may consume an excessive amount of gas and fail to execute,
125+
* thereby preventing other legitimate functions from executing. Epochs without contributions are excluded from funding.
126+
*/
127+
128+
function isEpochFunded(uint16 epochIndex) public view returns (bool) {
129+
if (epochIndex >= getEpochIndex()) {
130+
revert EpochNotYetEnded();
131+
}
132+
if (getEpochContributions(epochIndex).length == 0) {
133+
return false;
134+
}
135+
uint256 totalBudget = epochBudget * (epochIndex + 1);
136+
uint256 totalFundingReceived = rewardToken.balanceOf(address(this)) + claimsBalance;
137+
uint16 numberOfEpochsWithContributions = epochIndex + 1;
138+
return totalFundingReceived >= totalBudget;
139+
}
140+
141+
107142
/**
108143
* Calculates a contributor's percentage allocation of the budget for a given epoch.
109144
*

0 commit comments

Comments
 (0)