// 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 { // So this should guarantee that the proposal should not be able to be executed in future // But also, the proposal will be skipped each time. So the question is whether this, a silent // skip, or a require can be used to stay "concise", and abandon the safety of having also this assign // Outside dependencies, which don't exist as of yet, might believe that the proposal code was executed proposal.executed = true; // Let the event signify it was metamorphic 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; } }