Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ interface IProposalValidator is ISemver {
event ProposalTypeDataSet(
ProposalType proposalType,
uint256 requiredApprovals,
uint8 proposalVotingModule
uint8 idInConfigurator
);

event ProposalVotingModuleData(
Expand All @@ -85,7 +85,7 @@ interface IProposalValidator is ISemver {

struct ProposalTypeData {
uint256 requiredApprovals;
uint8 proposalVotingModule;
uint8 idInConfigurator;
}

struct VotingCycleData {
Expand Down Expand Up @@ -196,7 +196,7 @@ interface IProposalValidator is ISemver {

function OPTIMISTIC_MODULE_PERCENT_DIVISOR() external view returns (uint256);

function proposalTypesData(ProposalType) external view returns (uint256 requiredApprovals, uint8 proposalVotingModule);
function proposalTypesData(ProposalType) external view returns (uint256 requiredApprovals, uint8 idInConfigurator);

function votingCycles(uint256) external view returns (
uint256 startingTimestamp,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@
},
{
"internalType": "uint8",
"name": "proposalVotingModule",
"name": "idInConfigurator",
"type": "uint8"
}
],
Expand Down Expand Up @@ -332,7 +332,7 @@
},
{
"internalType": "uint8",
"name": "proposalVotingModule",
"name": "idInConfigurator",
"type": "uint8"
}
],
Expand Down Expand Up @@ -375,7 +375,7 @@
},
{
"internalType": "uint8",
"name": "proposalVotingModule",
"name": "idInConfigurator",
"type": "uint8"
}
],
Expand Down Expand Up @@ -736,7 +736,7 @@
{
"indexed": false,
"internalType": "uint8",
"name": "proposalVotingModule",
"name": "idInConfigurator",
"type": "uint8"
}
],
Expand Down
4 changes: 2 additions & 2 deletions packages/contracts-bedrock/snapshots/semver-lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,8 @@
"sourceCodeHash": "0x18f43b227decd0f2a895b8b55e23fa6a47706697c272bbf2482b3f912be446e1"
},
"src/governance/ProposalValidator.sol:ProposalValidator": {
"initCodeHash": "0xd359b54afbf8f0bfcde0e24b648d20f1eecdc306b511d3c0cd90afa5b61382ac",
"sourceCodeHash": "0x6da6042e1bc89da33dad2ce39aaef685f2a67c04e4693f69c2693b349899d131"
"initCodeHash": "0xca95fa18ecb8d7d44043dd60c545719e526fdf487ea405c8321d25b92782bfd6",
"sourceCodeHash": "0xf0b71a440952d0a4a00a488f5b98da2010d1972297876ea8ade494d0885f7508"
},
"src/legacy/DeployerWhitelist.sol:DeployerWhitelist": {
"initCodeHash": "0x53099379ed48b87f027d55712dbdd1da7d7099925426eb0531da9c0012e02c29",
Expand Down
100 changes: 53 additions & 47 deletions packages/contracts-bedrock/src/governance/ProposalValidator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,8 @@ contract ProposalValidator is OwnableUpgradeable, ReinitializableBase, ISemver {
/// @notice Emitted when the proposal type data is set.
/// @param proposalType The type of proposal.
/// @param requiredApprovals The required number of approvals.
/// @param proposalVotingModule The proposal type ID.
event ProposalTypeDataSet(ProposalType proposalType, uint256 requiredApprovals, uint8 proposalVotingModule);
/// @param idInConfigurator The proposal type ID.
event ProposalTypeDataSet(ProposalType proposalType, uint256 requiredApprovals, uint8 idInConfigurator);

/// @notice Emitted with ProposalSubmitted event.
/// @param proposalHash The hash of the submitted proposal.
Expand Down Expand Up @@ -165,10 +165,10 @@ contract ProposalValidator is OwnableUpgradeable, ReinitializableBase, ISemver {
/// @notice Struct for storing explicit data for each proposal type.
/// @param requiredApprovals The number of approvals each proposal type requires in order to be able to move for
/// voting.
/// @param proposalVotingModule The proposal type ID used to get the voting module from the configurator.
/// @param idInConfigurator The proposal type ID used to get the voting module from the configurator.
struct ProposalTypeData {
uint256 requiredApprovals;
uint8 proposalVotingModule;
uint8 idInConfigurator;
}

/// @notice Struct for storing voting cycle data.
Expand Down Expand Up @@ -325,8 +325,7 @@ contract ProposalValidator is OwnableUpgradeable, ReinitializableBase, ISemver {
}

// Validate voting cycle exists
VotingCycleData memory latestVotingCycleData = votingCycles[_latestVotingCycle];
if (latestVotingCycleData.startingTimestamp == 0) {
if (votingCycles[_latestVotingCycle].startingTimestamp == 0) {
revert ProposalValidator_InvalidVotingCycle();
}

Expand All @@ -338,24 +337,29 @@ contract ProposalValidator is OwnableUpgradeable, ReinitializableBase, ISemver {
revert ProposalValidator_InvalidAgainstThreshold();
}

// Create OptimisticModule ProposalSettings with required parameters
IOptimisticModule.ProposalSettings memory optimisticSettings = IOptimisticModule.ProposalSettings({
againstThreshold: _againstThreshold,
isRelativeToVotableSupply: true // MUST always be true
});

// Optimistic proposals are signal-only, no execution targets/calldatas needed
bytes memory proposalVotingModuleData = abi.encode(optimisticSettings);
bytes memory proposalVotingModuleData = abi.encode(
IOptimisticModule.ProposalSettings({
againstThreshold: _againstThreshold,
isRelativeToVotableSupply: true // MUST always be true
})
);

// Retrieve the ID to use in the proposal type configurator
uint8 idInConfigurator = proposalTypesData[_proposalType].idInConfigurator;

// Get the optimistic module address from configurator
IProposalTypesConfigurator.ProposalType memory proposalTypeConfig = IProposalTypesConfigurator(
GOVERNOR.PROPOSAL_TYPES_CONFIGURATOR()
).proposalTypes(proposalTypesData[_proposalType].proposalVotingModule);
address votingModule = proposalTypeConfig.module;
address votingModule;
{
IProposalTypesConfigurator.ProposalType memory proposalTypeConfig =
IProposalTypesConfigurator(GOVERNOR.PROPOSAL_TYPES_CONFIGURATOR()).proposalTypes(idInConfigurator);

// Validate voting module exists
if (bytes(proposalTypeConfig.name).length == 0) {
revert ProposalValidator_InvalidVotingModule();
// Validate voting module exists
if (bytes(proposalTypeConfig.name).length == 0) {
revert ProposalValidator_InvalidVotingModule();
}

votingModule = proposalTypeConfig.module;
}

// Generate unique proposal hash
Expand Down Expand Up @@ -387,7 +391,7 @@ contract ProposalValidator is OwnableUpgradeable, ReinitializableBase, ISemver {
proposal.movedToVote = true;

uint256 proposalId = GOVERNOR.proposeWithModule(
votingModule, proposalVotingModuleData, _proposalDescription, uint8(_proposalType)
votingModule, proposalVotingModuleData, _proposalDescription, idInConfigurator
);

// Make sure the proposalId is the same as the proposalHash
Expand Down Expand Up @@ -455,7 +459,7 @@ contract ProposalValidator is OwnableUpgradeable, ReinitializableBase, ISemver {
// Get the module address from the configurator
IProposalTypesConfigurator.ProposalType memory proposalTypeConfig = IProposalTypesConfigurator(
GOVERNOR.PROPOSAL_TYPES_CONFIGURATOR()
).proposalTypes(proposalTypesData[ProposalType.CouncilMemberElections].proposalVotingModule);
).proposalTypes(proposalTypesData[ProposalType.CouncilMemberElections].idInConfigurator);
address votingModule = proposalTypeConfig.module;

// Validate voting module exists
Expand Down Expand Up @@ -554,7 +558,7 @@ contract ProposalValidator is OwnableUpgradeable, ReinitializableBase, ISemver {
// Get the module address from the configurator
IProposalTypesConfigurator.ProposalType memory proposalTypeConfig = IProposalTypesConfigurator(
GOVERNOR.PROPOSAL_TYPES_CONFIGURATOR()
).proposalTypes(proposalTypesData[_proposalType].proposalVotingModule);
).proposalTypes(proposalTypesData[_proposalType].idInConfigurator);
address votingModule = proposalTypeConfig.module;

// Validate voting module exists
Expand Down Expand Up @@ -670,11 +674,13 @@ contract ProposalValidator is OwnableUpgradeable, ReinitializableBase, ISemver {

bytes memory proposalVotingModuleData = abi.encode(settings);

// Retrieve the ID to use in the proposal type configurator
uint8 idInConfigurator = proposalTypesData[ProposalType.ProtocolOrGovernorUpgrade].idInConfigurator;

// Get the module address from the configurator
ProposalType proposalType = ProposalType.ProtocolOrGovernorUpgrade;
address votingModule = IProposalTypesConfigurator(GOVERNOR.PROPOSAL_TYPES_CONFIGURATOR()).proposalTypes(
proposalTypesData[ProposalType.ProtocolOrGovernorUpgrade].proposalVotingModule
).module;
address votingModule =
IProposalTypesConfigurator(GOVERNOR.PROPOSAL_TYPES_CONFIGURATOR()).proposalTypes(idInConfigurator).module;

// Generate unique proposal hash
proposalHash_ =
Expand Down Expand Up @@ -705,9 +711,8 @@ contract ProposalValidator is OwnableUpgradeable, ReinitializableBase, ISemver {
proposal.movedToVote = true;

// Propose with module on the Governor
uint256 proposalId = GOVERNOR.proposeWithModule(
votingModule, proposalVotingModuleData, _proposalDescription, uint8(proposalType)
);
uint256 proposalId =
GOVERNOR.proposeWithModule(votingModule, proposalVotingModuleData, _proposalDescription, idInConfigurator);

// Make sure the proposalId is the same as the proposalHash
if (proposalId != uint256(proposalHash_)) {
Expand Down Expand Up @@ -745,11 +750,14 @@ contract ProposalValidator is OwnableUpgradeable, ReinitializableBase, ISemver {

bytes memory proposalVotingModuleData = abi.encode(options, settings);

ProposalType _proposalType = ProposalType.CouncilMemberElections;

// Retrieve the ID to use in the proposal type configurator
uint8 idInConfigurator = proposalTypesData[_proposalType].idInConfigurator;

// Get the module address from the configurator
ProposalType proposalType = ProposalType.CouncilMemberElections;
address votingModule = IProposalTypesConfigurator(GOVERNOR.PROPOSAL_TYPES_CONFIGURATOR()).proposalTypes(
proposalTypesData[proposalType].proposalVotingModule
).module;
address votingModule =
IProposalTypesConfigurator(GOVERNOR.PROPOSAL_TYPES_CONFIGURATOR()).proposalTypes(idInConfigurator).module;

// Generate unique proposal hash
proposalHash_ =
Expand All @@ -758,7 +766,7 @@ contract ProposalValidator is OwnableUpgradeable, ReinitializableBase, ISemver {
ProposalData storage proposal = _proposals[proposalHash_];

// Proposal must exist and be valid
if (proposal.proposer == address(0) || proposal.proposalType != proposalType) {
if (proposal.proposer == address(0) || proposal.proposalType != _proposalType) {
revert ProposalValidator_InvalidProposal();
}

Expand All @@ -768,7 +776,7 @@ contract ProposalValidator is OwnableUpgradeable, ReinitializableBase, ISemver {
}

// Check if proposal has enough approvals
if (proposal.approvalCount < proposalTypesData[proposalType].requiredApprovals) {
if (proposal.approvalCount < proposalTypesData[_proposalType].requiredApprovals) {
revert ProposalValidator_InsufficientApprovals();
}

Expand All @@ -789,9 +797,8 @@ contract ProposalValidator is OwnableUpgradeable, ReinitializableBase, ISemver {
proposal.movedToVote = true;

// Propose with module on the Governor
uint256 proposalId = GOVERNOR.proposeWithModule(
votingModule, proposalVotingModuleData, _proposalDescription, uint8(proposalType)
);
uint256 proposalId =
GOVERNOR.proposeWithModule(votingModule, proposalVotingModuleData, _proposalDescription, idInConfigurator);

// Make sure the proposalId is the same as the proposalHash
if (proposalId != uint256(proposalHash_)) {
Expand Down Expand Up @@ -824,7 +831,6 @@ contract ProposalValidator is OwnableUpgradeable, ReinitializableBase, ISemver {
external
returns (bytes32 proposalHash_)
{
uint256 optionsLength = _optionsDescriptions.length;
// Only funding proposal types can use this function
if (_proposalType != ProposalType.GovernanceFund && _proposalType != ProposalType.CouncilBudget) {
revert ProposalValidator_InvalidFundingProposalType();
Expand All @@ -836,7 +842,7 @@ contract ProposalValidator is OwnableUpgradeable, ReinitializableBase, ISemver {

// Configure approval module settings
IApprovalVotingModule.ProposalSettings memory settings = IApprovalVotingModule.ProposalSettings({
maxApprovals: uint8(optionsLength),
maxApprovals: uint8(_optionsDescriptions.length),
criteria: uint8(IApprovalVotingModule.PassingCriteria.Threshold),
budgetToken: Predeploys.GOVERNANCE_TOKEN,
criteriaValue: _criteriaValue,
Expand All @@ -845,10 +851,12 @@ contract ProposalValidator is OwnableUpgradeable, ReinitializableBase, ISemver {

bytes memory proposalVotingModuleData = abi.encode(options, settings);

// Retrieve the ID to use in the proposal type configurator
uint8 idInConfigurator = proposalTypesData[_proposalType].idInConfigurator;

// Get the module address from the configurator
address votingModule = IProposalTypesConfigurator(GOVERNOR.PROPOSAL_TYPES_CONFIGURATOR()).proposalTypes(
proposalTypesData[_proposalType].proposalVotingModule
).module;
address votingModule =
IProposalTypesConfigurator(GOVERNOR.PROPOSAL_TYPES_CONFIGURATOR()).proposalTypes(idInConfigurator).module;

// Generate unique proposal hash
proposalHash_ = _hashProposalWithModule(votingModule, proposalVotingModuleData, keccak256(bytes(_description)));
Expand Down Expand Up @@ -890,7 +898,7 @@ contract ProposalValidator is OwnableUpgradeable, ReinitializableBase, ISemver {

// Propose with module on the Governor
uint256 proposalId =
GOVERNOR.proposeWithModule(votingModule, proposalVotingModuleData, _description, uint8(_proposalType));
GOVERNOR.proposeWithModule(votingModule, proposalVotingModuleData, _description, idInConfigurator);

// Make sure the proposalId is the same as the proposalHash
if (proposalId != uint256(proposalHash_)) {
Expand Down Expand Up @@ -1143,8 +1151,6 @@ contract ProposalValidator is OwnableUpgradeable, ReinitializableBase, ISemver {
/// @param _proposalTypeData The data for the proposal type.
function _setProposalTypeData(ProposalType _proposalType, ProposalTypeData memory _proposalTypeData) private {
proposalTypesData[_proposalType] = _proposalTypeData;
emit ProposalTypeDataSet(
_proposalType, _proposalTypeData.requiredApprovals, _proposalTypeData.proposalVotingModule
);
emit ProposalTypeDataSet(_proposalType, _proposalTypeData.requiredApprovals, _proposalTypeData.idInConfigurator);
}
}
Loading