Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/token voting target improvements #38

Open
wants to merge 86 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
c4605ea
feat: update majority voting to support min approvals
clauBv23 Aug 26, 2024
5d955d8
ci: separate the updateMinApproval in a different function and add it…
clauBv23 Aug 26, 2024
6a2456c
feat: add minApproval to token voting, duplicate init function to con…
clauBv23 Aug 26, 2024
bdba026
fix: tests and compilation errors
clauBv23 Aug 26, 2024
88f9d04
feat: update the token voting setup so the min advance value in prope…
clauBv23 Aug 26, 2024
635b96c
fix: typo in the setup function selector
clauBv23 Aug 26, 2024
42ef256
feat: add new installation and update param in the build metadata file
clauBv23 Aug 26, 2024
77f3d6f
fix: update tests to work with new setup and configuration param
clauBv23 Aug 26, 2024
0403d51
feat: add natspec comments to the majority votes interface
clauBv23 Aug 26, 2024
902eb13
feat: add natspect comment to the token voting contract
clauBv23 Aug 26, 2024
7ec12c9
ci: remove not needed contract
clauBv23 Aug 26, 2024
59165e4
feat: add natspect and needed event when updating the min approval value
clauBv23 Aug 26, 2024
5d1c070
feat: add test for checking the proposal can not be executed when the…
clauBv23 Aug 28, 2024
b6e9ca7
feat: define new interfaces to check them on the tests
clauBv23 Aug 28, 2024
9b7394c
ci: move the min approval variable definition position
clauBv23 Aug 28, 2024
04ca7fb
fix: min approval values
clauBv23 Aug 28, 2024
8955f48
feat: add test for edge cases
clauBv23 Aug 28, 2024
638ea07
feat: modify the majority votes init function to receive the min appr…
clauBv23 Aug 28, 2024
7ec2e54
feat: add tets for checking the updateMinApproval function
clauBv23 Aug 28, 2024
e39d535
ci: remove comment
clauBv23 Aug 28, 2024
cb01be0
feat: add test for old interfaces on majority votes
clauBv23 Aug 28, 2024
f175112
fix: import missing constant
clauBv23 Aug 28, 2024
a959426
feat: add validation for minimal approval value
clauBv23 Aug 28, 2024
c0bd627
fixL typos
clauBv23 Aug 28, 2024
08409b5
feat: change test to the new initialize function
clauBv23 Aug 28, 2024
9bc036a
feat: define the initialize function signature as constant to reuse it
clauBv23 Aug 28, 2024
bb689ff
feat: revert on old initialize function
clauBv23 Aug 28, 2024
119e15c
feat: use new constant signatures and add test to check deprecated in…
clauBv23 Aug 28, 2024
7bf608b
ci: improve natspec comment
clauBv23 Aug 28, 2024
5c04b20
ci: remove comments
clauBv23 Aug 28, 2024
6f7d789
ci: remove comment
clauBv23 Aug 28, 2024
65198a0
ci: comment
clauBv23 Aug 28, 2024
8a69416
fix: typo
clauBv23 Aug 28, 2024
af67a74
feat: rename min approval variable
clauBv23 Aug 28, 2024
939dac7
fix: remove check no longer needed
clauBv23 Aug 28, 2024
1219954
ci: refact
clauBv23 Aug 28, 2024
210afb0
ci: remove comment
clauBv23 Aug 28, 2024
fb95ba5
ci: add comment
clauBv23 Aug 29, 2024
f7e0f97
fic: rename function for consistency
clauBv23 Aug 29, 2024
345d6b7
fix: update metadata description
clauBv23 Aug 29, 2024
4fe246c
fix lint
clauBv23 Aug 29, 2024
9b6cf85
ci: rename all vars name
clauBv23 Aug 29, 2024
92070c4
ci: rename functions for consistency
clauBv23 Aug 29, 2024
4ce4388
feat: change the min approval type from uint32 to uint256
clauBv23 Aug 29, 2024
c720fed
fix: test
clauBv23 Aug 29, 2024
1073c87
fix test
clauBv23 Aug 29, 2024
cb368a3
feat: add condition
clauBv23 Aug 30, 2024
6173c49
feat: add new params to token voting
clauBv23 Aug 30, 2024
7b44355
add target configs permanently and fix tests
novaknole Sep 8, 2024
5ce8060
reinitializer number fixed and old interface
novaknole Sep 10, 2024
84ef2cd
remove todo comments
novaknole Sep 10, 2024
207d988
initializeFrom with build number and data
novaknole Sep 10, 2024
5dfccfc
ivotes checks
novaknole Sep 17, 2024
b2eef30
add initialization modifier for safety + improved targetconfig
novaknole Sep 19, 2024
96bf27b
bytes param added
novaknole Sep 19, 2024
cd5543e
rename param function
novaknole Sep 19, 2024
42073e3
Update packages/contracts/src/TokenVoting.sol
novaknole Sep 25, 2024
2051e27
Update packages/contracts/src/TokenVoting.sol
novaknole Sep 25, 2024
70f28e6
fix typo
novaknole Sep 25, 2024
ccfe8ec
add delegate call
novaknole Sep 26, 2024
f3cb27c
silence warnings
novaknole Sep 26, 2024
386d417
add executor interface
novaknole Sep 26, 2024
329e76b
action as free level
novaknole Sep 27, 2024
283c2c6
Merge pull request #34 from aragon/feature/executors
novaknole Sep 27, 2024
fba0116
Merge pull request #32 from aragon/feature/bytes-param-add
novaknole Sep 27, 2024
6b02e12
remove unneccessary revoke
novaknole Sep 27, 2024
4a8be44
Merge branch 'feat/token-voting-target-improvements' into feature/bet…
novaknole Sep 27, 2024
41b5d7f
Merge pull request #31 from aragon/feature/better-ivote-checks
novaknole Sep 28, 2024
93e6d31
better upgrade tests
novaknole Sep 28, 2024
5178b67
remove hardcoded value
novaknole Sep 28, 2024
4780717
Merge pull request #35 from aragon/feature/add-initializeFrom-upgrade…
novaknole Sep 28, 2024
2690267
callinitialization from osx-commons
novaknole Sep 28, 2024
630bfd9
Merge branch 'feat/token-voting-target-improvements' of https://githu…
novaknole Sep 28, 2024
0647d5d
fix tohex
novaknole Sep 29, 2024
4f86c7c
metadata extension
novaknole Oct 8, 2024
f316675
Update packages/contracts/src/MajorityVotingBase.sol
novaknole Oct 8, 2024
ccfa5d9
Update packages/contracts/src/TokenVoting.sol
novaknole Oct 8, 2024
d49093c
Update packages/contracts/src/TokenVoting.sol
novaknole Oct 8, 2024
ab1af36
Update packages/contracts/src/TokenVoting.sol
novaknole Oct 8, 2024
3176cd4
Update packages/contracts/src/TokenVotingSetup.sol
novaknole Oct 8, 2024
3de9e37
Update packages/contracts/src/TokenVotingSetup.sol
novaknole Oct 8, 2024
9799f4e
Update packages/contracts/src/TokenVotingSetup.sol
novaknole Oct 8, 2024
7b3d080
permission added
novaknole Oct 8, 2024
ba6dcf8
Merge pull request #36 from aragon/feature/metadata
novaknole Oct 8, 2024
4e5d291
metadata rename
novaknole Oct 9, 2024
a857d9e
fix tests and contract (#37)
novaknole Oct 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions packages/contracts/deploy/20_new_version/23_publish.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,12 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
createVersion: {
_release: VERSION.release,
_pluginSetup: setup.address,
_buildMetadata: toHex(buildMetadataURI),
_releaseMetadata: toHex(releaseMetadataURI),
_buildMetadata: ethers.utils.hexlify(
ethers.utils.toUtf8Bytes(buildMetadataURI)
),
_releaseMetadata: ethers.utils.hexlify(
ethers.utils.toUtf8Bytes(releaseMetadataURI)
),
},
},
],
Expand Down
2 changes: 1 addition & 1 deletion packages/contracts/hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ const config: HardhatUserConfig = {
deploy: './deploy',
},
mocha: {
timeout: 60_000,
timeout: 6000000,
},
solidity: {
version: '0.8.17',
Expand Down
11 changes: 11 additions & 0 deletions packages/contracts/src/IMajorityVoting.sol
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ interface IMajorityVoting {
/// @return The support threshold parameter.
function supportThreshold() external view returns (uint32);

/// @notice Returns the min approval value stored configured.
/// @return The minimal approval value.
function minApproval() external view returns (uint256);

/// @notice Returns the minimum participation parameter stored in the voting settings.
/// @return The minimum participation parameter.
function minParticipation() external view returns (uint32);
Expand All @@ -61,6 +65,13 @@ interface IMajorityVoting {
/// @return Returns `true` if the participation is greater than the minimum participation and `false` otherwise.
function isMinParticipationReached(uint256 _proposalId) external view returns (bool);

/// @notice Checks if the min approval value defined as:
///$$\texttt{minApproval} = \frac{N_\text{yes}}{N_\text{total}}$$
/// for a proposal vote is greater or equal than the minimum approval value.
/// @param _proposalId The ID of the proposal.
/// @return Returns `true` if the participation is greater than the minimum participation and `false` otherwise.
function isMinApprovalReached(uint256 _proposalId) external view returns (bool);

/// @notice Checks if an account can participate on a proposal vote. This can be because the vote
/// - has not started,
/// - has ended,
Expand Down
119 changes: 103 additions & 16 deletions packages/contracts/src/MajorityVotingBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ import {ProposalUpgradeable} from "@aragon/osx-commons-contracts/src/plugin/exte
import {RATIO_BASE, RatioOutOfBounds} from "@aragon/osx-commons-contracts/src/utils/math/Ratio.sol";
import {PluginUUPSUpgradeable} from "@aragon/osx-commons-contracts/src/plugin/PluginUUPSUpgradeable.sol";
import {IDAO} from "@aragon/osx-commons-contracts/src/dao/IDAO.sol";
import {IProposal} from "@aragon/osx-commons-contracts/src/plugin/extensions/proposal/IProposal.sol";
import {Action} from "@aragon/osx-commons-contracts/src/executors/IExecutor.sol";
import {MetadataExtensionUpgradeable} from "@aragon/osx-commons-contracts/src/utils/metadata/MetadataExtensionUpgradeable.sol";

import {IMajorityVoting} from "./IMajorityVoting.sol";

Expand Down Expand Up @@ -120,6 +123,7 @@ abstract contract MajorityVotingBase is
IMajorityVoting,
Initializable,
ERC165Upgradeable,
MetadataExtensionUpgradeable,
PluginUUPSUpgradeable,
ProposalUpgradeable
{
Expand Down Expand Up @@ -165,15 +169,18 @@ abstract contract MajorityVotingBase is
/// @param voters The votes casted by the voters.
/// @param actions The actions to be executed when the proposal passes.
/// @param allowFailureMap A bitmap allowing the proposal to succeed, even if individual actions might revert.
/// @param minApprovalPower The minimum amount of yes votes power needed for the proposal advance.
/// If the bit at index `i` is 1, the proposal succeeds even if the `i`th action reverts.
/// A failure map value of 0 requires every action to not revert.
struct Proposal {
bool executed;
ProposalParameters parameters;
Tally tally;
mapping(address => IMajorityVoting.VoteOption) voters;
IDAO.Action[] actions;
Action[] actions;
uint256 allowFailureMap;
uint256 minApprovalPower;
TargetConfig targetConfig; // added in v1.3
}

/// @notice A container for the proposal parameters at the time of proposal creation.
Expand Down Expand Up @@ -211,19 +218,31 @@ abstract contract MajorityVotingBase is
this.totalVotingPower.selector ^
this.getProposal.selector ^
this.updateVotingSettings.selector ^
this.createProposal.selector;
this.updateMinApprovals.selector ^
bytes4(
keccak256(
"createProposal(bytes,(address,uint256,bytes)[],uint256,uint64,uint64,uint8,bool)"
)
);

/// @notice The ID of the permission required to call the `updateVotingSettings` function.
bytes32 public constant UPDATE_VOTING_SETTINGS_PERMISSION_ID =
keccak256("UPDATE_VOTING_SETTINGS_PERMISSION");

/// @notice The ID of the permission required to call the `addAddresses` and `removeAddresses` functions.
bytes32 public constant CREATE_PROPOSAL_PERMISSION_ID = keccak256("CREATE_PROPOSAL_PERMISSION");

/// @notice A mapping between proposal IDs and proposal information.
// solhint-disable-next-line named-parameters-mapping
mapping(uint256 => Proposal) internal proposals;

/// @notice The struct storing the voting settings.
VotingSettings private votingSettings;

/// @notice The minimal ratio of yes votes needed for a proposal succeed.
/// @dev is not on the VotingSettings for compatibility reasons.
uint256 private minApprovals; // added in v1.3

/// @notice Thrown if a date is out of bounds.
/// @param limit The limit value.
/// @param actual The actual value.
Expand Down Expand Up @@ -252,6 +271,10 @@ abstract contract MajorityVotingBase is
/// @param proposalId The ID of the proposal.
error ProposalExecutionForbidden(uint256 proposalId);

/// @notice Thrown if the proposal with same actions and metadata already exists.
/// @param proposalId The id of the proposal.
error ProposalAlreadyExists(uint256 proposalId);

/// @notice Emitted when the voting settings are updated.
/// @param votingMode A parameter to select the vote mode.
/// @param supportThreshold The support threshold value.
Expand All @@ -266,17 +289,27 @@ abstract contract MajorityVotingBase is
uint256 minProposerVotingPower
);

/// @notice Emitted when the min approval value is updated.
/// @param minApprovals The minimum amount of yes votes needed for a proposal succeed.
event VotingMinApprovalUpdated(uint256 minApprovals);

/// @notice Initializes the component to be used by inheriting contracts.
/// @dev This method is required to support [ERC-1822](https://eips.ethereum.org/EIPS/eip-1822).
/// @param _dao The IDAO interface of the associated DAO.
/// @param _votingSettings The voting settings.
// solhint-disable-next-line func-name-mixedcase
function __MajorityVotingBase_init(
IDAO _dao,
VotingSettings calldata _votingSettings
VotingSettings calldata _votingSettings,
TargetConfig calldata _targetConfig,
uint256 _minApprovals,
bytes calldata _pluginMetadata
) internal onlyInitializing {
__PluginUUPSUpgradeable_init(_dao);
_updateVotingSettings(_votingSettings);
_updateMinApprovals(_minApprovals);
_setTargetConfig(_targetConfig);
_setMetadata(_pluginMetadata);
}

/// @notice Checks if this or the parent contract supports an interface by its ID.
Expand All @@ -288,12 +321,25 @@ abstract contract MajorityVotingBase is
public
view
virtual
override(ERC165Upgradeable, PluginUUPSUpgradeable, ProposalUpgradeable)
override(
ERC165Upgradeable,
MetadataExtensionUpgradeable,
PluginUUPSUpgradeable,
ProposalUpgradeable
)
returns (bool)
{
// In addition to the current IMajorityVoting interface, also support previous version
// that did not include the `isMinApprovalReached` and `minApproval` functions, same
// happens with MAJORITY_VOTING_BASE_INTERFACE which did not include `updateMinApprovals`.
return
_interfaceId == MAJORITY_VOTING_BASE_INTERFACE_ID ||
_interfaceId == MAJORITY_VOTING_BASE_INTERFACE_ID ^ this.updateMinApprovals.selector ||
_interfaceId == type(IMajorityVoting).interfaceId ||
_interfaceId ==
type(IMajorityVoting).interfaceId ^
this.isMinApprovalReached.selector ^
this.minApproval.selector ||
super.supportsInterface(_interfaceId);
}

Expand Down Expand Up @@ -341,7 +387,9 @@ abstract contract MajorityVotingBase is
}

/// @inheritdoc IMajorityVoting
function canExecute(uint256 _proposalId) public view virtual returns (bool) {
function canExecute(
uint256 _proposalId
) public view virtual override(IMajorityVoting, IProposal) returns (bool) {
return _canExecute(_proposalId);
}

Expand Down Expand Up @@ -386,6 +434,16 @@ abstract contract MajorityVotingBase is
proposal_.parameters.minVotingPower;
}

/// @inheritdoc IMajorityVoting
function isMinApprovalReached(uint256 _proposalId) public view virtual returns (bool) {
return proposals[_proposalId].tally.yes >= proposals[_proposalId].minApprovalPower;
}

/// @inheritdoc IMajorityVoting
function minApproval() public view virtual returns (uint256) {
return minApprovals;
}

/// @inheritdoc IMajorityVoting
function supportThreshold() public view virtual returns (uint32) {
return votingSettings.supportThreshold;
Expand Down Expand Up @@ -438,7 +496,7 @@ abstract contract MajorityVotingBase is
bool executed,
ProposalParameters memory parameters,
Tally memory tally,
IDAO.Action[] memory actions,
Action[] memory actions,
uint256 allowFailureMap
)
{
Expand All @@ -460,6 +518,14 @@ abstract contract MajorityVotingBase is
_updateVotingSettings(_votingSettings);
}

/// @notice Updates the minimal approval value.
/// @param _minApprovals The new minimal approval value.
function updateMinApprovals(
uint256 _minApprovals
) external virtual auth(UPDATE_VOTING_SETTINGS_PERMISSION_ID) {
_updateMinApprovals(_minApprovals);
}

/// @notice Creates a new majority voting proposal.
/// @param _metadata The metadata of the proposal.
/// @param _actions The actions that will be executed after the proposal passes.
Expand All @@ -477,7 +543,7 @@ abstract contract MajorityVotingBase is
/// @return proposalId The ID of the proposal.
function createProposal(
bytes calldata _metadata,
IDAO.Action[] calldata _actions,
Action[] calldata _actions,
uint256 _allowFailureMap,
uint64 _startDate,
uint64 _endDate,
Expand All @@ -500,14 +566,19 @@ abstract contract MajorityVotingBase is
/// @notice Internal function to execute a vote. It assumes the queried proposal exists.
/// @param _proposalId The ID of the proposal.
function _execute(uint256 _proposalId) internal virtual {
proposals[_proposalId].executed = true;
Proposal storage proposal_ = proposals[_proposalId];

proposal_.executed = true;

_executeProposal(
dao(),
_proposalId,
proposals[_proposalId].actions,
proposals[_proposalId].allowFailureMap
_execute(
proposal_.targetConfig.target,
bytes32(_proposalId),
proposal_.actions,
proposal_.allowFailureMap,
proposal_.targetConfig.operation
);

emit ProposalExecuted(_proposalId);
}

/// @notice Internal function to check if a voter can vote. It assumes the queried proposal exists.
Expand Down Expand Up @@ -550,6 +621,9 @@ abstract contract MajorityVotingBase is
if (!isMinParticipationReached(_proposalId)) {
return false;
}
if (!isMinApprovalReached(_proposalId)) {
return false;
}

return true;
}
Expand All @@ -570,7 +644,7 @@ abstract contract MajorityVotingBase is
/// @param _votingSettings The voting settings to be validated and updated.
function _updateVotingSettings(VotingSettings calldata _votingSettings) internal virtual {
// Require the support threshold value to be in the interval [0, 10^6-1],
// because `>` comparision is used in the support criterion and >100% could never be reached.
// because `>` comparison is used in the support criterion and >100% could never be reached.
if (_votingSettings.supportThreshold > RATIO_BASE - 1) {
revert RatioOutOfBounds({
limit: RATIO_BASE - 1,
Expand All @@ -579,7 +653,7 @@ abstract contract MajorityVotingBase is
}

// Require the minimum participation value to be in the interval [0, 10^6],
// because `>=` comparision is used in the participation criterion.
// because `>=` comparison is used in the participation criterion.
if (_votingSettings.minParticipation > RATIO_BASE) {
revert RatioOutOfBounds({limit: RATIO_BASE, actual: _votingSettings.minParticipation});
}
Expand All @@ -603,6 +677,19 @@ abstract contract MajorityVotingBase is
});
}

/// @notice Internal function to update minimal approval value.
/// @param _minApprovals The new minimal approval value.
function _updateMinApprovals(uint256 _minApprovals) internal virtual {
// Require the minimum approval value to be in the interval [0, 10^6],
// because `>=` comparison is used in the participation criterion.
if (_minApprovals > RATIO_BASE) {
revert RatioOutOfBounds({limit: RATIO_BASE, actual: _minApprovals});
}

minApprovals = _minApprovals;
emit VotingMinApprovalUpdated(_minApprovals);
}

/// @notice Validates and returns the proposal vote dates.
/// @param _start The start date of the proposal vote.
/// If 0, the current timestamp is used and the vote starts immediately.
Expand Down Expand Up @@ -644,5 +731,5 @@ abstract contract MajorityVotingBase is
/// new variables without shifting down storage in the inheritance chain
/// (see [OpenZeppelin's guide about storage gaps]
/// (https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps)).
uint256[47] private __gap;
uint256[46] private __gap;
}
Loading
Loading