2023-06-12 16:22:32 +03:00
|
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
pragma solidity ^0.6.12;
|
|
|
|
pragma experimental ABIEncoderV2;
|
|
|
|
|
|
|
|
import { Utils } from "./Utils.sol";
|
|
|
|
import { Proposal, IGovernance } from "./interfaces/IGovernance.sol";
|
|
|
|
|
2023-06-14 02:39:58 +03:00
|
|
|
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
|
|
|
2023-06-12 16:22:32 +03:00
|
|
|
contract ProposalUtils is Utils {
|
|
|
|
IGovernance internal governance = IGovernance(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 governance.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) {
|
2023-06-14 02:39:58 +03:00
|
|
|
retrieveAndLockBalance(TEST_PRIVATE_KEY_ONE, TEST_ADDRESS_ONE, PROPOSAL_THRESHOLD + 1 ether);
|
2023-06-12 16:22:32 +03:00
|
|
|
|
|
|
|
/* ----------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();
|
|
|
|
/* ------------------------------ */
|
|
|
|
|
|
|
|
return proposalId;
|
|
|
|
}
|
|
|
|
|
|
|
|
function proposeAndExecute(address proposalAddress) public {
|
|
|
|
uint256 proposalId = proposeAndVote(proposalAddress);
|
|
|
|
|
|
|
|
waitUntilExecutable(proposalId);
|
|
|
|
IGovernance(_governanceAddress).execute(proposalId);
|
2023-06-14 02:39:58 +03:00
|
|
|
|
|
|
|
returnTokensToGovernanceAfterVoting(proposalId);
|
|
|
|
}
|
|
|
|
|
|
|
|
function returnTokensToGovernanceAfterVoting(uint256 proposalId) public {
|
|
|
|
uint256 retrievedAmount = PROPOSAL_THRESHOLD + 1 ether;
|
|
|
|
|
|
|
|
uint256 proposalExecutableTime = getProposalExecutableTime(proposalId);
|
|
|
|
uint256 tokensUnlockTime = proposalExecutableTime + 4 days + 1 seconds;
|
|
|
|
|
|
|
|
if(block.timestamp < tokensUnlockTime) vm.warp(tokensUnlockTime);
|
|
|
|
|
|
|
|
vm.startPrank(TEST_ADDRESS_ONE);
|
|
|
|
|
|
|
|
governance.unlock(retrievedAmount);
|
|
|
|
IERC20(_tokenAddress).transfer(_governanceAddress, retrievedAmount);
|
|
|
|
|
|
|
|
vm.stopPrank();
|
2023-06-12 16:22:32 +03:00
|
|
|
}
|
|
|
|
}
|