// SPDX-License-Identifier: MIT pragma solidity ^0.6.12; pragma experimental ABIEncoderV2; import { Utils } from "./Utils.sol"; import { Proposal, IGovernance } from "@interfaces/IGovernance.sol"; import { GovernancePatchUpgrade } from "@root/v4-patch/GovernancePatchUpgrade.sol"; contract ProposalUtils is Utils { GovernancePatchUpgrade internal governance = GovernancePatchUpgrade(payable(_governanceAddress)); function getProposalExecutableTime(uint256 proposalId) internal view returns (uint256) { Proposal memory proposal = getProposal(proposalId); return proposal.endTime + PROPOSAL_LOCKED_DURATION + 1 seconds; } function getProposal(uint256 proposalId) internal view returns (Proposal memory){ return IGovernance(_governanceAddress).proposals(proposalId); } function hasProposal(uint256 proposalId) internal view returns (bool){ return governance.proposalCount() >= proposalId; } function waitUntilExecutable(uint256 proposalId) internal { uint256 proposalExecutableTime = getProposalExecutableTime(proposalId); require(block.timestamp < proposalExecutableTime + PROPOSAL_EXECUTION_MAX_DURATION, "Too late to execute proposal"); vm.warp(proposalExecutableTime); } function proposeAndVote(address proposalAddress) public returns (uint256) { retrieveAndLockBalance(TEST_PRIVATE_KEY_ONE, TEST_ADDRESS_ONE, PROPOSAL_THRESHOLD); retrieveAndLockBalance(TEST_PRIVATE_KEY_TWO, TEST_ADDRESS_TWO, 1 ether); /* ----------PROPOSER------------ */ vm.startPrank(TEST_ADDRESS_ONE); uint256 proposalId = governance.propose(proposalAddress, PROPOSAL_DESCRIPTION); // TIME-TRAVEL vm.warp(block.timestamp + 6 hours); governance.castVote(proposalId, true); vm.stopPrank(); /* ------------------------------ */ /* -------------VOTER-------------*/ vm.startPrank(TEST_ADDRESS_TWO); governance.castVote(proposalId, true); vm.stopPrank(); /* ------------------------------ */ return proposalId; } function proposeAndExecute(address proposalAddress) public { uint256 proposalId = proposeAndVote(proposalAddress); waitUntilExecutable(proposalId); IGovernance(_governanceAddress).execute(proposalId); } }