remove governance feature from GhostERC20 contract

Signed-off-by: Uncle Fatso <uncle.fatso@ghostchain.io>
This commit is contained in:
Uncle Fatso 2026-09-14 11:03:55 +03:00
parent b1e9be968e
commit 59a13fec9d
Signed by: f4ts0
GPG Key ID: 565F4F2860226EBB
4 changed files with 9 additions and 717 deletions

View File

@ -3,7 +3,7 @@ set -e
AVAILABLE_NETWORKS=(anvil-localnet sepolia-testnet hoodi-testnet mordor-testnet)
NETWORK="${AVAILABLE_NETWORKS[0]}"
START=1
END=13
END=12
VERIFY_NEEDED="--verify"
LEGACY_FLAGS=""
@ -25,10 +25,9 @@ usage() {
echo "7) BondDepository"
echo "8) StakingDistributor"
echo "9) BondingCalculator"
echo "10) Governor"
echo "11) AfterPartyFirst"
echo "12) AfterPartySecond"
echo "13) AfterPartyThird"
echo "10) AfterPartyFirst"
echo "11) AfterPartySecond"
echo "12) AfterPartyThird"
echo "69) Gatekeeper"
exit 1
}
@ -111,12 +110,10 @@ for i in $(seq $START $END); do
elif [ "9" == "$i" ]; then
CONTRACT="BondingCalculator"
elif [ "10" == "$i" ]; then
CONTRACT="Governor"
elif [ "11" == "$i" ]; then
CONTRACT="AfterPartyFirst"
elif [ "12" == "$i" ]; then
elif [ "11" == "$i" ]; then
CONTRACT="AfterPartySecond"
elif [ "13" == "$i" ]; then
elif [ "12" == "$i" ]; then
CONTRACT="AfterPartyThird"
elif [ "69" == "$i" ]; then
CONTRACT="Gatekeeper"

View File

@ -2,25 +2,17 @@
pragma solidity ^0.8.20;
import {ERC20} from "@openzeppelin-contracts/token/ERC20/ERC20.sol";
import {ERC20Permit} from "@openzeppelin-contracts/token/ERC20/extensions/ERC20Permit.sol";
import {ERC20Votes} from "@openzeppelin-contracts/token/ERC20/extensions/ERC20Votes.sol";
import {Nonces} from "@openzeppelin-contracts/utils/Nonces.sol";
import {ISTNK} from "./interfaces/ISTNK.sol";
import {IGHST} from "./interfaces/IGHST.sol";
import {FullMath} from "./libraries/FullMath.sol";
contract Ghost is IGHST, ERC20, ERC20Permit, ERC20Votes {
contract Ghost is IGHST, ERC20 {
address public override staking;
address public override stnk;
address private _initializer;
error GhostDelegationIsBuiltIn();
constructor(address _stnk, string memory name, string memory symbol)
ERC20(name, symbol)
ERC20Permit(name)
{
constructor(address _stnk, string memory name, string memory symbol) ERC20(name, symbol) {
stnk = _stnk;
_initializer = msg.sender;
}
@ -41,21 +33,6 @@ contract Ghost is IGHST, ERC20, ERC20Permit, ERC20Votes {
_burn(_from, _amount);
}
function delegate(address) public override pure {
revert GhostDelegationIsBuiltIn();
}
function delegateBySig(
address,
uint256,
uint256,
uint8,
bytes32,
bytes32
) public override pure {
revert GhostDelegationIsBuiltIn();
}
function index() public view override returns (uint256) {
return ISTNK(stnk).index();
}
@ -67,16 +44,4 @@ contract Ghost is IGHST, ERC20, ERC20Permit, ERC20Votes {
function balanceTo(uint256 _amount) public view override returns (uint256) {
return FullMath.mulDiv(_amount, 1e18, index());
}
function nonces(address owner) public view override(ERC20Permit, Nonces) returns (uint256) {
return super.nonces(owner);
}
function delegates(address account) public pure override returns (address) {
return account;
}
function _update(address from, address to, uint256 amount) internal override(ERC20, ERC20Votes) {
super._update(from, to, amount);
}
}

View File

@ -1,647 +0,0 @@
pragma solidity 0.8.20;
import {Test} from "forge-std/Test.sol";
import {Strings} from "@openzeppelin-contracts/utils/Strings.sol";
import {Ghost} from "../../src/GhstERC20.sol";
import {Stinky} from "../../src/StinkyERC20.sol";
import {GhostGovernor} from "../../src/governance/GhostGovernor.sol";
import {IGovernor} from "@openzeppelin-contracts/governance/IGovernor.sol";
import {IVotes} from "@openzeppelin-contracts/governance/utils/IVotes.sol";
import {SafeERC20} from "@openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol";
contract GhostGovernorExposed is GhostGovernor {
constructor(
IVotes _ghst,
uint48 _initialVoteExtension,
uint48 _initialVotingDelay,
uint32 _initialVotingPeriod,
uint256 _initialProposalThreshold,
uint256 _quorumFraction
) GhostGovernor(
_ghst,
_initialVoteExtension,
_initialVotingDelay,
_initialVotingPeriod,
_initialProposalThreshold,
_quorumFraction
) {}
function isValidDescriptionForProposer(
address proposer,
string memory description
) public view returns (bool) {
return super._isValidDescriptionForProposer(proposer, description);
}
function quorumReached(uint256 proposalId) public view returns (bool) {
return super._quorumReached(proposalId);
}
function voteSucceeded(uint256 proposalId) public view returns (bool) {
return super._voteSucceeded(proposalId);
}
}
contract GhostGovernorTest is Test {
using Strings for address;
using SafeERC20 for Ghost;
uint48 public constant VOTE_EXTENSION = 69;
uint48 public constant VOTING_DELAY = 420;
uint32 public constant VOTING_PERIOD = 1337;
uint256 public constant PROPOSAL_THRESHOLD = 69 * 1e18;
uint256 public constant QUORUM_FRACTION = 20; // percent
address constant INIT = 0x0000000000000000000000000000000000000001;
address constant ALICE = 0x0000000000000000000000000000000000000002;
address constant BOB = 0x0000000000000000000000000000000000000003;
address constant CAROL = 0x0000000000000000000000000000000000000004;
address constant DAVE = 0x0000000000000000000000000000000000000005;
address constant EVE = 0x0000000000000000000000000000000000000006;
GhostGovernorExposed public governor;
Stinky public stnk;
Ghost public ghst;
function setUp() public {
vm.startPrank(INIT);
stnk = new Stinky(10819917194513808e56, "Stinky Test Name", "STNKTST");
ghst = new Ghost(address(stnk), "Ghost Test Name", "GHSTTST");
ghst.initialize(INIT);
governor = new GhostGovernorExposed(
ghst,
VOTE_EXTENSION,
VOTING_DELAY,
VOTING_PERIOD,
PROPOSAL_THRESHOLD,
QUORUM_FRACTION
);
vm.stopPrank();
vm.prank(ALICE);
ghst.approve(address(governor), type(uint256).max);
vm.prank(BOB);
ghst.approve(address(governor), type(uint256).max);
vm.prank(CAROL);
ghst.approve(address(governor), type(uint256).max);
}
function test_correctGovernanceName() public view {
assertEq(governor.name(), "GhostGovernorV1");
}
function test_correctGovernanceVersion() public view {
assertEq(governor.version(), "1");
}
function test_correctGovernanceConfig() public view {
assertEq(governor.COUNTING_MODE(), "support=bravo&quorum=for");
}
function test_correctGovernanceProposalThreshold() public view {
assertEq(governor.proposalThreshold(), PROPOSAL_THRESHOLD);
}
function test_correctGovernanceVotingDelay() public view {
assertEq(governor.votingDelay(), VOTING_DELAY);
}
function test_correctGovernanceVotingPeriod() public view {
assertEq(governor.votingPeriod(), VOTING_PERIOD);
}
function test_correctGovernanceVoteExtension() public view {
assertEq(governor.lateQuorumVoteExtension(), VOTE_EXTENSION);
}
function test_correctGovernanceQuorumFraction() public view {
assertEq(governor.quorumNumerator(), QUORUM_FRACTION);
}
function test_validDescriptionForProposer(
string memory description,
address proposer,
bool includeProposer
) public view {
string memory finalDescription = description;
if (includeProposer) {
finalDescription = string.concat(
description,
"#proposer=",
Strings.toHexString(proposer)
);
}
bool isValid = governor.isValidDescriptionForProposer(proposer, finalDescription);
assertTrue(isValid);
}
function test_invalidDescriptionForProposer(
string memory description,
address commitProposer,
address actualProposer
) public view {
vm.assume(commitProposer != actualProposer);
string memory wrongDescription = string.concat(
description,
"#proposer=",
Strings.toHexString(commitProposer)
);
bool isValid = governor.isValidDescriptionForProposer(actualProposer, wrongDescription);
assertFalse(isValid);
}
function test_succeededOnAbsoluteMajority() public {
vm.startPrank(INIT);
ghst.mint(ALICE, PROPOSAL_THRESHOLD);
ghst.mint(BOB, 555 * 1e17);
ghst.mint(CAROL, 345 * 1e17 + 1);
ghst.mint(DAVE, 21 * 1e18);
vm.stopPrank();
vm.roll(block.number + 1);
(uint256 proposalId,,,,) = _proposeDummy(ALICE, 69);
_waitForActive(proposalId);
assertEq(uint8(governor.state(proposalId)), uint8(IGovernor.ProposalState.Active));
_castVoteWrapper(proposalId, BOB, 1, true, true);
assertEq(uint8(governor.state(proposalId)), uint8(IGovernor.ProposalState.Succeeded));
vm.expectRevert();
vm.prank(CAROL);
governor.castVote(proposalId, 0);
vm.expectRevert();
vm.prank(DAVE);
governor.castVote(proposalId, 0);
}
function test_defeatedOnAbsoluteMajority() public {
vm.startPrank(INIT);
ghst.mint(ALICE, PROPOSAL_THRESHOLD);
ghst.mint(BOB, 555 * 1e17);
ghst.mint(CAROL, 345 * 1e17 + 1);
ghst.mint(DAVE, 21 * 1e18);
vm.stopPrank();
vm.roll(block.number + 1);
(uint256 proposalId,,,,) = _proposeDummy(ALICE, 69);
_waitForActive(proposalId);
assertEq(uint8(governor.state(proposalId)), uint8(IGovernor.ProposalState.Active));
_castVoteWrapper(proposalId, BOB, 0, true, false);
assertEq(uint8(governor.state(proposalId)), uint8(IGovernor.ProposalState.Active));
_castVoteWrapper(proposalId, CAROL, 0, true, false);
assertEq(uint8(governor.state(proposalId)), uint8(IGovernor.ProposalState.Defeated));
vm.expectRevert();
vm.prank(DAVE);
governor.castVote(proposalId, 1);
}
function test_onlyOneActiveProposal() public {
uint256 amount = PROPOSAL_THRESHOLD;
vm.startPrank(INIT);
ghst.mint(ALICE, amount);
ghst.mint(BOB, 2 * amount);
ghst.mint(CAROL, 3 * amount);
vm.stopPrank();
vm.roll(block.number + 1);
(uint256 proposalId,,,,) = _proposeDummy(ALICE, 69);
_waitForActive(proposalId);
vm.prank(ALICE);
assertEq(governor.releaseLocked(proposalId), 0);
assertEq(governor.lockedAmounts(proposalId), amount);
assertEq(ghst.balanceOf(ALICE), 0);
(uint256 againstVotes, uint256 forVotes, uint256 abstainVotes) = governor.proposalVotes(proposalId);
assertEq(againstVotes, 0);
assertEq(forVotes, amount);
assertEq(abstainVotes, 0);
_castVoteWrapper(proposalId, BOB, 1, true, true);
(againstVotes, forVotes, abstainVotes) = governor.proposalVotes(proposalId);
assertEq(againstVotes, 0);
assertEq(forVotes, 3 * amount);
assertEq(abstainVotes, 0);
assertEq(ghst.balanceOf(ALICE), 0);
assertEq(ghst.balanceOf(BOB), 2 * amount);
assertEq(ghst.balanceOf(CAROL), 3 * amount);
_waitForSucceed(proposalId);
vm.prank(ALICE);
assertEq(governor.releaseLocked(proposalId), amount);
assertEq(governor.lockedAmounts(proposalId), 0);
assertEq(ghst.balanceOf(ALICE), amount);
vm.prank(ALICE);
assertEq(governor.releaseLocked(proposalId), 0);
assertEq(governor.lockedAmounts(proposalId), 0);
assertEq(ghst.balanceOf(ALICE), amount);
assertEq(ghst.balanceOf(ALICE), amount);
assertEq(ghst.balanceOf(BOB), 2 * amount);
assertEq(ghst.balanceOf(CAROL), 3 * amount);
(proposalId,,,,) = _proposeDummy(BOB, 420);
_waitForActive(proposalId);
_castVoteWrapper(proposalId, ALICE, 1, true, true);
_castVoteWrapper(proposalId, CAROL, 1, true, true);
vm.roll(block.number + 3);
(uint256 newProposalId,,,,) = _proposeDummy(CAROL, 1337);
assertEq(uint8(governor.state(proposalId)), uint8(IGovernor.ProposalState.Succeeded));
assertEq(uint8(governor.state(newProposalId)), uint8(IGovernor.ProposalState.Pending));
assertEq(ghst.balanceOf(ALICE), amount);
assertEq(ghst.balanceOf(BOB), 0);
assertEq(ghst.balanceOf(CAROL), 0);
vm.prank(BOB);
assertEq(governor.releaseLocked(proposalId), 2 * amount);
assertEq(governor.lockedAmounts(proposalId), 0);
assertEq(ghst.balanceOf(BOB), 2 * amount);
vm.prank(CAROL);
assertEq(governor.releaseLocked(newProposalId), 0);
assertEq(governor.lockedAmounts(newProposalId), 3 * amount);
assertEq(ghst.balanceOf(CAROL), 0);
}
function test_proposalCountWorks() public {
assertEq(governor.proposalCount(), 0);
uint256 i = 1;
for (; i < 69; ) {
{
uint256 amount = governor.activeProposedLock() + PROPOSAL_THRESHOLD;
if (amount + ghst.totalSupply() > type(uint208).max) {
break;
}
vm.prank(INIT);
ghst.mint(ALICE, amount);
vm.roll(block.number + 1);
}
(
uint256 proposalId,
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
string memory description
) = _proposeDummy(ALICE, i);
{
(
address[] memory thisTargets,
uint256[] memory thisValues,
bytes[] memory thisCalldatas,
bytes32 thisDescriptionHash
) = governor.proposalDetails(proposalId);
assertEq(thisTargets.length, targets.length);
assertEq(thisValues.length, values.length);
assertEq(thisCalldatas.length, calldatas.length);
assertEq(thisTargets[0], targets[0]);
assertEq(thisValues[0], values[0]);
assertEq(thisCalldatas[0], calldatas[0]);
assertEq(thisDescriptionHash, keccak256(bytes(description)));
}
{
(
uint256 otherProposalId,
address[] memory otherTargets,
uint256[] memory otherValues,
bytes[] memory otherCalldatas,
bytes32 otherDescriptionHash
) = governor.proposalDetailsAt(i - 1);
assertEq(otherTargets.length, targets.length);
assertEq(otherValues.length, values.length);
assertEq(otherCalldatas.length, calldatas.length);
assertEq(otherProposalId, governor.hashProposal(targets, values, calldatas, keccak256(bytes(description))));
assertEq(otherTargets[0], targets[0]);
assertEq(otherValues[0], values[0]);
assertEq(otherCalldatas[0], calldatas[0]);
assertEq(otherDescriptionHash, keccak256(bytes(description)));
}
assertEq(governor.proposalCount(), i);
unchecked { ++i; }
}
}
function test_preventLateQuorumWorks() public {
vm.startPrank(INIT);
ghst.mint(ALICE, PROPOSAL_THRESHOLD);
ghst.mint(BOB, 50 * 1e18);
ghst.mint(CAROL, 100 * 1e18);
ghst.mint(DAVE, 100 * 1e18);
ghst.mint(EVE, 500 * 1e18);
vm.stopPrank();
vm.roll(block.number + 1);
(uint256 proposalId,,,,) = _proposeDummy(ALICE, 69);
assertEq(uint8(governor.state(proposalId)), uint8(IGovernor.ProposalState.Pending));
vm.roll(block.number + VOTING_DELAY + 1);
assertEq(uint8(governor.state(proposalId)), uint8(IGovernor.ProposalState.Active));
assertEq(governor.voteOf(proposalId, BOB), 0);
assertEq(governor.voteOf(proposalId, CAROL), 0);
assertEq(governor.voteOf(proposalId, DAVE), 0);
assertEq(governor.voteOf(proposalId, EVE), 0);
vm.roll(governor.proposalDeadline(proposalId));
_castVoteWrapper(proposalId, BOB, 1, false, true);
vm.roll(governor.proposalDeadline(proposalId));
_castVoteWrapper(proposalId, CAROL, 0, true, false);
vm.roll(governor.proposalDeadline(proposalId));
_castVoteWrapper(proposalId, DAVE, 1, true, false);
vm.roll(governor.proposalDeadline(proposalId));
_castVoteWrapper(proposalId, EVE, 1, true, true);
vm.prank(ALICE);
governor.execute(proposalId);
assertEq(uint8(governor.state(proposalId)), uint8(IGovernor.ProposalState.Executed));
assertEq(governor.voteOf(proposalId, BOB), 2);
assertEq(governor.voteOf(proposalId, CAROL), 1);
assertEq(governor.voteOf(proposalId, DAVE), 2);
assertEq(governor.voteOf(proposalId, EVE), 2);
}
function test_quorumNumeratorWorks() public {
uint256 numerator = governor.quorumNumerator();
uint256 denominator = governor.quorumDenominator();
uint256 currentBlock = block.number;
vm.startPrank(INIT);
ghst.mint(ALICE, 1 * 1e18);
ghst.mint(BOB, 69 * 1e18);
ghst.mint(CAROL, 420 * 1e18);
ghst.mint(DAVE, 1337 * 1e18);
ghst.mint(EVE, 69420 * 1e18);
vm.stopPrank();
vm.roll(currentBlock + 2);
assertEq(governor.quorum(currentBlock), 71247 * 1e18 * numerator / denominator);
}
function test_votingPowerTransfer() public {
vm.startPrank(INIT);
ghst.mint(ALICE, 35 * 1e18);
ghst.mint(BOB, 34 * 1e18);
vm.stopPrank();
vm.roll(block.number + 1);
vm.expectRevert();
vm.prank(ALICE);
ghst.delegate(ALICE);
vm.expectRevert();
vm.prank(BOB);
ghst.delegate(BOB);
_assertVotesEqualToBalance();
vm.prank(ALICE);
ghst.safeTransfer(BOB, 420);
_assertVotesEqualToBalance();
uint256 aliceBalance = ghst.balanceOf(ALICE);
vm.prank(ALICE);
ghst.safeTransfer(BOB, aliceBalance);
_assertVotesEqualToBalance();
vm.prank(BOB);
ghst.safeTransfer(CAROL, 1337);
_assertVotesEqualToBalance();
uint256 bobBalance = ghst.balanceOf(BOB);
vm.prank(BOB);
ghst.safeTransfer(CAROL, bobBalance);
_assertVotesEqualToBalance();
vm.expectRevert();
vm.prank(CAROL);
ghst.delegate(CAROL);
assertEq(ghst.getVotes(ALICE), 0);
assertEq(ghst.getVotes(BOB), 0);
assertEq(ghst.getVotes(CAROL), 69 * 1e18);
assertEq(ghst.balanceOf(ALICE), 0);
assertEq(ghst.balanceOf(BOB), 0);
assertEq(ghst.balanceOf(CAROL), 69 * 1e18);
vm.prank(INIT);
ghst.burn(CAROL, 69 * 1e18);
assertEq(ghst.getVotes(CAROL), 0);
assertEq(ghst.balanceOf(CAROL), 0);
assertEq(ghst.totalSupply(), 0);
}
function test_changesOfTotalSupplyHasNoAffectOnPastTotalSupply() public {
vm.prank(INIT);
ghst.mint(ALICE, 100);
vm.roll(block.number + 1);
assertEq(ghst.getPastTotalSupply(block.number - 1), 100);
assertEq(ghst.totalSupply(), 100);
vm.prank(INIT);
ghst.burn(ALICE, 50);
vm.roll(block.number + 1);
assertEq(ghst.getPastTotalSupply(block.number - 2), 100);
assertEq(ghst.getPastTotalSupply(block.number - 1), 50);
assertEq(ghst.totalSupply(), 50);
vm.prank(INIT);
ghst.mint(BOB, 150);
vm.roll(block.number + 1);
assertEq(ghst.getPastTotalSupply(block.number - 3), 100);
assertEq(ghst.getPastTotalSupply(block.number - 2), 50);
assertEq(ghst.getPastTotalSupply(block.number - 1), 200);
assertEq(ghst.totalSupply(), 200);
}
function test_proposeAutoForVote() public {
vm.startPrank(INIT);
ghst.mint(ALICE, PROPOSAL_THRESHOLD);
vm.stopPrank();
vm.roll(block.number + 1);
(uint256 proposalId,,,,) = _proposeDummy(ALICE, 69);
(uint256 againstVotes, uint256 forVotes, uint256 abstainVotes) = governor.proposalVotes(proposalId);
assertEq(forVotes, PROPOSAL_THRESHOLD);
assertEq(againstVotes, 0);
assertEq(abstainVotes, 0);
vm.roll(block.number + 1);
vm.expectRevert();
vm.prank(ALICE);
governor.castVote(proposalId, 1);
}
function test_releaseAfterDefeated() public {
vm.startPrank(INIT);
ghst.mint(ALICE, PROPOSAL_THRESHOLD);
ghst.mint(BOB, PROPOSAL_THRESHOLD);
ghst.mint(CAROL, PROPOSAL_THRESHOLD);
vm.stopPrank();
vm.roll(block.number + 1);
(uint256 proposalId,,,,) = _proposeDummy(ALICE, 69);
assertEq(governor.releaseLocked(proposalId), 0);
assertEq(ghst.balanceOf(ALICE), 0);
assertEq(ghst.balanceOf(address(governor)), PROPOSAL_THRESHOLD);
_waitForActive(proposalId);
_castVoteWrapper(proposalId, BOB, 0, true, false);
_castVoteWrapper(proposalId, CAROL, 0, true, false);
assertEq(uint8(governor.state(proposalId)), uint8(IGovernor.ProposalState.Defeated));
assertEq(governor.releaseLocked(proposalId), PROPOSAL_THRESHOLD);
assertEq(ghst.balanceOf(ALICE), PROPOSAL_THRESHOLD);
assertEq(ghst.balanceOf(address(governor)), 0);
}
function test_releaseAfterSucceeded() public {
vm.startPrank(INIT);
ghst.mint(ALICE, PROPOSAL_THRESHOLD);
ghst.mint(BOB, PROPOSAL_THRESHOLD);
ghst.mint(CAROL, PROPOSAL_THRESHOLD);
vm.stopPrank();
vm.roll(block.number + 1);
(uint256 proposalId,,,,) = _proposeDummy(ALICE, 69);
assertEq(governor.releaseLocked(proposalId), 0);
assertEq(ghst.balanceOf(ALICE), 0);
assertEq(ghst.balanceOf(address(governor)), PROPOSAL_THRESHOLD);
_waitForActive(proposalId);
_castVoteWrapper(proposalId, BOB, 1, true, true);
assertEq(uint8(governor.state(proposalId)), uint8(IGovernor.ProposalState.Succeeded));
assertEq(governor.releaseLocked(proposalId), PROPOSAL_THRESHOLD);
assertEq(ghst.balanceOf(ALICE), PROPOSAL_THRESHOLD);
assertEq(ghst.balanceOf(address(governor)), 0);
}
function test_releaseAfterDeadline() public {
vm.startPrank(INIT);
ghst.mint(ALICE, PROPOSAL_THRESHOLD);
ghst.mint(BOB, 420 * PROPOSAL_THRESHOLD);
vm.stopPrank();
vm.roll(block.number + 1);
(uint256 proposalId,,,,) = _proposeDummy(ALICE, 69);
assertEq(governor.releaseLocked(proposalId), 0);
assertEq(ghst.balanceOf(ALICE), 0);
assertEq(ghst.balanceOf(address(governor)), PROPOSAL_THRESHOLD);
_waitForActive(proposalId);
vm.roll(block.number + governor.proposalDeadline(proposalId));
assertEq(uint8(governor.state(proposalId)), uint8(IGovernor.ProposalState.Defeated));
assertEq(governor.releaseLocked(proposalId), PROPOSAL_THRESHOLD);
assertEq(ghst.balanceOf(ALICE), PROPOSAL_THRESHOLD);
assertEq(ghst.balanceOf(address(governor)), 0);
}
function _proposeDummy(address who, uint256 index)
private
returns (
uint256 proposalId,
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
string memory description
)
{
targets = new address[](1);
targets[0] = address(uint160(index + 1)); // forge-lint: disable-line(unsafe-typecast)
values = new uint256[](1);
values[0] = 0;
calldatas = new bytes[](1);
calldatas[0] = abi.encodeWithSignature("setVotingDelay(uint48)", 0);
description = string.concat("Proposal #", Strings.toString(index));
vm.prank(who);
proposalId = governor.propose(
targets,
values,
calldatas,
description
);
vm.roll(block.number + 1);
}
function _castVoteWrapper(
uint256 proposalId,
address who,
uint8 vote,
bool isQuorumReached,
bool isVoteSucceeded
) private {
assertEq(governor.hasVoted(proposalId, who), false);
vm.prank(who);
governor.castVote(proposalId, vote);
assertEq(governor.hasVoted(proposalId, who), true);
assertEq(governor.quorumReached(proposalId), isQuorumReached);
assertEq(governor.voteSucceeded(proposalId), isVoteSucceeded);
}
function _assertVotesEqualToBalance() private view {
assertEq(ghst.getVotes(ALICE), ghst.balanceOf(ALICE));
assertEq(ghst.getVotes(BOB), ghst.balanceOf(BOB));
assertEq(ghst.getVotes(CAROL), ghst.balanceOf(CAROL));
}
function _waitForActive(uint256 proposalId) private {
assertEq(uint8(governor.state(proposalId)), uint8(IGovernor.ProposalState.Pending));
vm.roll(block.number + VOTING_DELAY + 1);
assertEq(uint8(governor.state(proposalId)), uint8(IGovernor.ProposalState.Active));
}
function _waitForSucceed(uint256 proposalId) private {
assertEq(uint8(governor.state(proposalId)), uint8(IGovernor.ProposalState.Active));
vm.roll(governor.proposalDeadline(proposalId) + 1);
assertEq(uint8(governor.state(proposalId)), uint8(IGovernor.ProposalState.Succeeded));
}
}

View File

@ -7,18 +7,10 @@ import {Stinky} from "../../src/StinkyERC20.sol";
import {GhostAuthority} from "../../src/GhostAuthority.sol";
import {GhostStaking} from "../../src/Staking.sol";
import {ERC20PermitTest} from "./Permit.t.sol";
import {ERC20AllowanceTest} from "./Allowance.t.sol";
import {ERC20TransferTest} from "./Transfer.t.sol";
import {ERC20VotesTest} from "./Votes.t.sol";
contract GhostTest is
Test,
ERC20PermitTest,
ERC20AllowanceTest,
ERC20TransferTest,
ERC20VotesTest
{
contract GhostTest is Test, ERC20AllowanceTest, ERC20TransferTest {
uint256 constant public INITIAL_INDEX = 10819917194513808e56;
address constant INITIALIZER = 0x0000000000000000000000000000000000000001;
@ -59,10 +51,8 @@ contract GhostTest is
ghst.initialize(address(staking));
vm.stopPrank();
initializePermit(address(ghst), AMOUNT, MAX_AMOUNT);
initializeAllowance(ALICE, BOB, address(ghst), AMOUNT, MAX_AMOUNT, AMOUNT);
initializeTransfer(ALICE, BOB, address(ghst), AMOUNT, MAX_AMOUNT);
initializeVotes(ALICE, BOB, address(ghst), AMOUNT);
}
function test_isConstructedCorrectly() public view {
@ -157,19 +147,6 @@ contract GhostTest is
_mintTokens(who, value);
}
function _mintPermitTokens(address who, uint256 value) internal override {
_mintTokens(who, value);
}
function _mintVotesTokens(address who, uint256 value) internal override {
_mintTokens(who, value);
}
function _burnVotesTokens(address who, uint256 value) internal override {
vm.prank(address(staking));
ghst.burn(who, value);
}
function _getCurrentTotalSupply() internal override view returns (uint256) {
return ghst.totalSupply();
}