80 lines
2.7 KiB
Solidity
80 lines
2.7 KiB
Solidity
|
// SPDX-License-Identifier: MIT
|
||
|
pragma solidity ^0.8.19;
|
||
|
|
||
|
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||
|
|
||
|
import { Utils } from "./Utils.sol";
|
||
|
import { Proposal, IGovernance } from "@interfaces/IGovernance.sol";
|
||
|
|
||
|
contract ProposalUtils is Utils {
|
||
|
IGovernance internal governance = IGovernance(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) {
|
||
|
retrieveAndLockBalance(TEST_PRIVATE_KEY_ONE, TEST_ADDRESS_ONE, PROPOSAL_QOURUM_THRESHOLD + 1 ether);
|
||
|
|
||
|
/* ----------PROPOSE------------ */
|
||
|
vm.startPrank(TEST_ADDRESS_ONE);
|
||
|
|
||
|
uint256 proposalId = governance.propose(proposalAddress, PROPOSAL_DESCRIPTION);
|
||
|
|
||
|
/* ------------------------------ */
|
||
|
|
||
|
// TIME-TRAVEL
|
||
|
vm.warp(block.timestamp + 6 hours);
|
||
|
|
||
|
/* ------------VOTE-------------- */
|
||
|
|
||
|
governance.castVote(proposalId, true);
|
||
|
|
||
|
vm.stopPrank();
|
||
|
/* ------------------------------ */
|
||
|
|
||
|
return proposalId;
|
||
|
}
|
||
|
|
||
|
function proposeAndExecute(address proposalAddress) public {
|
||
|
uint256 proposalId = proposeAndVote(proposalAddress);
|
||
|
|
||
|
waitUntilExecutable(proposalId);
|
||
|
governance.execute(proposalId);
|
||
|
|
||
|
returnTokensToGovernanceAfterVoting(proposalId);
|
||
|
}
|
||
|
|
||
|
function returnTokensToGovernanceAfterVoting(uint256 proposalId) public {
|
||
|
uint256 retrievedAmount = PROPOSAL_QOURUM_THRESHOLD + 1 ether;
|
||
|
|
||
|
uint256 proposalExecutableTime = getProposalExecutableTime(proposalId);
|
||
|
uint256 tokensUnlockTime = proposalExecutableTime + PROPOSAL_VOTE_EXTEND_TIME + PROPOSAL_EXECUTION_MAX_DURATION + 1 seconds;
|
||
|
|
||
|
if (block.timestamp < tokensUnlockTime) vm.warp(tokensUnlockTime);
|
||
|
|
||
|
vm.startPrank(TEST_ADDRESS_ONE);
|
||
|
|
||
|
governance.unlock(retrievedAmount);
|
||
|
IERC20(tornTokenAddress).transfer(governanceAddress, retrievedAmount);
|
||
|
|
||
|
vm.stopPrank();
|
||
|
}
|
||
|
}
|