-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
0cf4854
commit 7738767
Showing
6 changed files
with
232 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.20; | ||
|
||
import { Question } from "./Question.sol"; | ||
import { IOpenQuestion, IQuestion } from "./interfaces/IOpenQuestion.sol"; | ||
|
||
/// @title OpenQuestion Contract | ||
/// @dev Implements an open-ended question where users can add options and vote | ||
contract OpenQuestion is Question, IOpenQuestion { | ||
// Mapping to store user votes for each option | ||
mapping(address voter => mapping(uint256 optionId => bool hasVoted)) private userVotes; | ||
|
||
/// @inheritdoc IOpenQuestion | ||
/// @notice Minimum points required to add an option | ||
uint256 public override minPointsToAddOption; | ||
|
||
/// @notice Initializes the OpenQuestion contract | ||
/// @dev Sets up the question details and minimum points required to add an option | ||
/// @param initialOwner The address of the initial owner of the question | ||
/// @param _title The title of the question | ||
/// @param _description The description of the question | ||
/// @param _deadline The deadline for voting on the question | ||
/// @param _pointsAddress The address of the Points contract | ||
/// @param _minPointsToAddOption The minimum points required to add a new option | ||
constructor( | ||
address initialOwner, | ||
string memory _title, | ||
string memory _description, | ||
uint256 _deadline, | ||
address _pointsAddress, | ||
uint256 _minPointsToAddOption | ||
) Question(initialOwner, _title, _description, _deadline, _pointsAddress) { | ||
questionType = QuestionType.Open; | ||
minPointsToAddOption = _minPointsToAddOption; | ||
} | ||
|
||
/// @inheritdoc IOpenQuestion | ||
/// @notice Adds a new option to the question | ||
/// @dev Checks if the user has sufficient points to add the option | ||
/// @param _title The title of the new option | ||
/// @param _description The description of the new option | ||
function addOption(string memory _title, string memory _description) external override { | ||
if (points.balanceAtTimestamp(msg.sender, deadline) < minPointsToAddOption) { | ||
revert InsufficientPoints(); | ||
} | ||
_addOption(_title, _description); | ||
} | ||
|
||
/// @notice Processes a vote for a specific option | ||
/// @dev Overrides the base _processVote function to check for duplicate votes | ||
/// @param optionId The ID of the option being voted for | ||
function _processVote(uint256 optionId) internal override { | ||
if (userVotes[msg.sender][optionId]) { | ||
revert UserAlreadyVotedThisOption(msg.sender, optionId); | ||
} | ||
userVotes[msg.sender][optionId] = true; | ||
} | ||
|
||
/// @inheritdoc IQuestion | ||
/// @notice Checks if a user has voted for a specific option | ||
/// @dev Returns true if the user has voted for the option, false otherwise | ||
/// @param voter The address of the user | ||
/// @param optionId The ID of the option | ||
function hasVoted( | ||
address voter, | ||
uint256 optionId | ||
) public view override(IQuestion, Question) returns (bool) { | ||
return userVotes[voter][optionId]; | ||
} | ||
|
||
/// @inheritdoc IOpenQuestion | ||
/// @notice Updates the minimum points required to add a new option | ||
/// @dev Only callable by the owner | ||
/// @param _minPointsToAddOption The new minimum points required | ||
function updateMinPointsToAddOption(uint256 _minPointsToAddOption) external override onlyOwner { | ||
minPointsToAddOption = _minPointsToAddOption; | ||
emit MinPointsToAddOptionUpdated(_minPointsToAddOption); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.20; | ||
|
||
import { IQuestion } from "./IQuestion.sol"; | ||
|
||
/// @title IFixedQuestion Interface | ||
/// @notice Interface for fixed-choice voting questions | ||
/// @dev Extends the IQuestion interface with specific functionality for fixed-choice questions | ||
interface IFixedQuestion is IQuestion { | ||
/// @notice Error thrown when a user attempts to vote more than once | ||
/// @dev This error should be used in the implementation to prevent multiple votes from the same user | ||
error UserAlreadyVoted(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.20; | ||
|
||
import { IQuestion } from "./IQuestion.sol"; | ||
|
||
/// @title IOpenQuestion Interface | ||
/// @dev Interface for an open-ended question where users can add new options | ||
interface IOpenQuestion is IQuestion { | ||
/// @notice Thrown when a user tries to add an option without sufficient points | ||
error InsufficientPoints(); | ||
|
||
/// @notice Thrown when a user tries to vote for an option they've already voted for | ||
/// @param voter The address of the voter | ||
/// @param optionId The ID of the option | ||
error UserAlreadyVotedThisOption(address voter, uint256 optionId); | ||
|
||
/// @notice Emitted when the minimum points required to add an option is updated | ||
/// @param newMinPoints The new minimum points value | ||
event MinPointsToAddOptionUpdated(uint256 newMinPoints); | ||
|
||
/// @notice Returns the minimum points required to add a new option | ||
/// @return The minimum points required | ||
function minPointsToAddOption() external view returns (uint256); | ||
|
||
/// @notice Adds a new option to the question | ||
/// @dev Requires the caller to have sufficient points | ||
/// @param _title The title of the new option | ||
/// @param _description The description of the new option | ||
function addOption(string memory _title, string memory _description) external; | ||
|
||
/// @notice Updates the minimum points required to add a new option | ||
/// @dev Can only be called by the contract owner or authorized role | ||
/// @param _minPointsToAddOption The new minimum points value | ||
function updateMinPointsToAddOption(uint256 _minPointsToAddOption) external; | ||
} |
Oops, something went wrong.