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
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": "0xe7a93826772bf108a21923f7e45b1f46cdadb75e48b0c796e43d64f0c1d81504",
"sourceCodeHash": "0xadd8e049bf3c652af123b6c64a1d504c92be13b4797ab10b978df907b05dcf7f"
"initCodeHash": "0x06a2b713907a4a4c961061edeb8f9417f9fdf63fc5512e6794af67fcc548935d",
"sourceCodeHash": "0x98cb001a29058d9d4bdd017c73e3520af1e22e9dee15e153799196b3390923df"
},
"src/legacy/DeployerWhitelist.sol:DeployerWhitelist": {
"initCodeHash": "0x53099379ed48b87f027d55712dbdd1da7d7099925426eb0531da9c0012e02c29",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -369,10 +369,15 @@ contract ProposalValidator is OwnableUpgradeable, ReinitializableBase, ISemver {
if (_proposalType == ProposalType.MaintenanceUpgrade) {
proposal.movedToVote = true;

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

// Make sure the proposalId is the same as the proposalHash
if (proposalId != uint256(proposalHash_)) {
revert ProposalValidator_ProposalIdMismatch();
}

emit ProposalMovedToVote(proposalHash_, msg.sender);
}
}
Expand Down
38 changes: 38 additions & 0 deletions packages/contracts-bedrock/test/governance/ProposalValidator.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -1077,6 +1077,44 @@ contract ProposalValidator_SubmitUpgradeProposal_TestFail is ProposalValidator_I
againstThreshold, proposalDescription, attestationUid, proposalType, CYCLE_NUMBER
);
}

function test_submitUpgradeProposal_proposalIdMismatch_reverts(uint256 proposalId) public {
uint248 againstThreshold = 5000;
ProposalValidator.ProposalType proposalType = ProposalValidator.ProposalType.MaintenanceUpgrade;
bytes32 attestationUid = _createApprovedProposerAttestation(topDelegate_A, proposalType);

// Calculate expected proposal hash
bytes memory votingModuleData = _constructOptimisticVotingModuleData(againstThreshold);
bytes32 expectedHash = validator.hashProposalWithModule(
optimisticVotingModule, votingModuleData, keccak256(bytes(proposalDescription))
);

vm.assume(proposalId != uint256(expectedHash)); // Ensure proposalId is different from expectedHash

_mockProposalTypesConfiguratorCall(OPTIMISTIC_VOTING_MODULE_ID);

_mockAndExpect(
address(governor),
abi.encodeCall(IOptimismGovernor.proposalSnapshot, (uint256(expectedHash))),
abi.encode(0)
);

// Mock the proposeWithModule call to return a different proposalId
_mockAndExpect(
address(governor),
abi.encodeCall(
IOptimismGovernor.proposeWithModule,
(optimisticVotingModule, votingModuleData, proposalDescription, uint8(proposalType))
),
abi.encode(proposalId)
);

vm.expectRevert(ProposalValidator.ProposalValidator_ProposalIdMismatch.selector);
vm.prank(topDelegate_A);
validator.submitUpgradeProposal(
againstThreshold, proposalDescription, attestationUid, proposalType, CYCLE_NUMBER
);
}
}

/// @title ProposalValidator_SubmitCouncilMemberElectionsProposal_Test
Expand Down