// SPDX-License-Identifier: MIT pragma solidity ^0.6.12; pragma experimental ABIEncoderV2; import "../v1/Governance.sol"; import "../v3-relayer-registry/GovernanceStakingUpgrade.sol"; contract GovernancePatchUpgrade is GovernanceStakingUpgrade { mapping(uint256 => bytes32) public proposalCodehashes; event CodehashDifferent(address target, bytes32 oldHash, bytes32 newHash); // The stakingRewardsAddress sets the immutable to the new staking contract constructor( address stakingRewardsAddress, address gasCompLogic, address userVaultAddress ) public GovernanceStakingUpgrade(stakingRewardsAddress, gasCompLogic, userVaultAddress) {} // This should guarantee that the proposal extcodehashes are good function execute(uint256 proposalId) public payable virtual override(Governance) { require(msg.sender != address(this), "pseudo-external function"); Proposal storage proposal = proposals[proposalId]; address target = proposal.target; bytes32 proposalCodehash; assembly { proposalCodehash := extcodehash(target) } if (proposalCodehash == proposalCodehashes[proposalId]) { super.execute(proposalId); } else { // Note that this is the easiest way to block further execution proposal.executed = true; // Let the event signify it was broken emit CodehashDifferent(target, proposalCodehashes[proposalId], proposalCodehash); } } // This should store the proposal extcodehash function _propose( address proposer, address target, string memory description ) internal virtual override(Governance) returns (uint256 proposalId) { // Implies all former predicates were valid proposalId = super._propose(proposer, target, description); bytes32 proposalCodehash; assembly { proposalCodehash := extcodehash(target) } proposalCodehashes[proposalId] = proposalCodehash; } }