Skip to content

Commit

Permalink
Added test framework with minimal deploy script (#17)
Browse files Browse the repository at this point in the history
* Added test framework with minimal deploy script

* forge fmt constant cleanup

* Added TODO about constants
  • Loading branch information
jferas authored and wildmolasses committed Nov 1, 2024
1 parent 9302835 commit 5309e98
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 9 deletions.
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ contracts*
typechain-types
out
lib
script
11 changes: 6 additions & 5 deletions contracts/CompoundGovernor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -33,38 +33,39 @@ contract CompoundGovernor is
{
/// @notice The number of votes supporting a proposal required for quorum for a vote to succeed
/// TODO: This will be replaced as a settable quorum in a future PR.
uint256 public constant quorumVotes = 400_000e18; // 400,000 = 4% of Comp
uint256 public quorumVotes;

/// @notice Disables the initialize function.
constructor() {
_disableInitializers();
}

/// @notice Initialize Governor.
/// @param _name The name of the Governor.
/// @param _initialVotingDelay The initial voting delay.
/// @param _initialVotingPeriod The initial voting period.
/// @param _initialProposalThreshold The initial proposal threshold.
/// @param _compAddress The address of the Comp token.
/// @param _quorumVotes The quorum votes.
/// @param _timelockAddress The address of the Timelock.
/// @param _initialVoteExtension The initial vote extension.
/// @param _initialOwner The initial owner of the Governor.
function initialize(
string memory _name,
uint48 _initialVotingDelay,
uint32 _initialVotingPeriod,
uint256 _initialProposalThreshold,
IVotes _compAddress,
uint256 _quorumVotes,
ICompoundTimelock _timelockAddress,
uint48 _initialVoteExtension,
address _initialOwner
) public initializer {
__Governor_init(_name);
__Governor_init("Compound Governor");
__GovernorSettings_init(_initialVotingDelay, _initialVotingPeriod, _initialProposalThreshold);
__GovernorVotes_init(_compAddress);
__GovernorTimelockCompound_init(_timelockAddress);
__GovernorPreventLateQuorum_init(_initialVoteExtension);
__Ownable_init(_initialOwner);
quorumVotes = _quorumVotes;
}

/// @inheritdoc GovernorTimelockCompoundUpgradeable
Expand Down Expand Up @@ -179,7 +180,7 @@ contract CompoundGovernor is
/// @notice Calculates the quorum size, excludes token delegated to the exclude address.
/// @dev We override this function to use the circulating supply to calculate the quorum.
/// @return The quorum size.
function quorum(uint256) public pure override(GovernorUpgradeable) returns (uint256) {
function quorum(uint256) public view override(GovernorUpgradeable) returns (uint256) {
return quorumVotes;
}
}
33 changes: 29 additions & 4 deletions contracts/test/CompoundGovernor.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,35 @@
pragma solidity 0.8.26;

import {Test, console2} from "forge-std/Test.sol";
import {CompoundGovernorConstants} from "script/CompoundGovernorConstants.sol";
import {DeployCompoundGovernor} from "script/DeployCompoundGovernor.s.sol";
import {CompoundGovernor} from "contracts/CompoundGovernor.sol";

// TODO: implement actual CompoundGovernor tests. This is just a placeholder to satisfy "forge test".
contract CompoundGovernorTest is Test {
function test() public pure {
assertEq(true, true);
contract CompoundGovernorTest is Test, CompoundGovernorConstants {
CompoundGovernor governor;
address owner;

function setUp() public {
// set the owner of the governor (use the anvil default account #0, if no environment variable is set)
owner = vm.envOr("DEPLOYER_ADDRESS", 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266);

// set the RPC URL and the fork block number to create a local execution fork for testing
vm.createSelectFork(vm.envOr("RPC_URL", string("Please set RPC_URL in your .env file")), FORK_BLOCK);

// Deploy the CompoundGovernor contract
DeployCompoundGovernor _deployer = new DeployCompoundGovernor();
_deployer.setUp();
governor = _deployer.run(owner);
}

function testInitialize() public view {
assertEq(governor.quorumVotes(), INITIAL_QUORUM);
assertEq(governor.votingPeriod(), INITIAL_VOTING_PERIOD);
assertEq(governor.votingDelay(), INITIAL_VOTING_DELAY);
assertEq(governor.proposalThreshold(), INITIAL_PROPOSAL_THRESHOLD);
assertEq(governor.lateQuorumVoteExtension(), INITIAL_VOTE_EXTENSION);
assertEq(address(governor.timelock()), TIMELOCK_ADDRESS);
assertEq(address(governor.token()), COMP_TOKEN_ADDRESS);
assertEq(governor.owner(), owner);
}
}
5 changes: 5 additions & 0 deletions example.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
RPC_URL=
ETHERSCAN_API_KEY=
DEPLOYER_ADDRESS=
DEPLOYER_PRIVATE_KEY=

25 changes: 25 additions & 0 deletions script/CompoundGovernorConstants.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// SPDX-License-Identifier: MIT
// slither-disable-start reentrancy-benign
pragma solidity 0.8.26;

contract CompoundGovernorConstants {
// TODO: Verify these values are correct for launch of the CompoundGovernor

// These constants are taken from the existing GovernorBravoDelegate contract.

uint48 INITIAL_VOTING_DELAY = 13_140; // The delay before voting takes place, in blocks
uint32 INITIAL_VOTING_PERIOD = 19_710; // The duration of voting on a proposal, in blocks
uint256 INITIAL_PROPOSAL_THRESHOLD = 25_000e18; // Votes required in order for a voter to become proposer
uint256 INITIAL_QUORUM = 400_000e18; // 400,000 = 4% of Comp

uint48 INITIAL_VOTE_EXTENSION = 7200; // Prevents sudden token moves before voting ends (2 days of blocks)

// The address of the COMP token
address COMP_TOKEN_ADDRESS = 0xc00e94Cb662C3520282E6f5717214004A7f26888;

// The address of the Timelock
address payable TIMELOCK_ADDRESS = payable(0x6d903f6003cca6255D85CcA4D3B5E5146dC33925);

// The fork block for testing
uint256 FORK_BLOCK = 20_885_000;
}
49 changes: 49 additions & 0 deletions script/DeployCompoundGovernor.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// SPDX-License-Identifier: BSD-3-Clause
// slither-disable-start reentrancy-benign

pragma solidity 0.8.26;

import {Script} from "forge-std/Script.sol";
import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
import {IVotes} from "@openzeppelin/contracts/governance/utils/IVotes.sol";
import {ICompoundTimelock} from "@openzeppelin/contracts/vendor/compound/ICompoundTimelock.sol";
import {CompoundGovernor} from "contracts/CompoundGovernor.sol";
import {CompoundGovernorConstants} from "script/CompoundGovernorConstants.sol";

// Deploy script for the underlying implementation that will be used by both Governor proxies
contract DeployCompoundGovernor is Script, CompoundGovernorConstants {
uint256 deployerPrivateKey;

function setUp() public virtual {
// private key of the deployer (use the anvil default account #0 key, if no environment variable is set)
deployerPrivateKey = vm.envOr(
"DEPLOYER_PRIVATE_KEY", uint256(0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80)
);
}

function run(address _owner) public returns (CompoundGovernor _governor) {
vm.startBroadcast(deployerPrivateKey);

// Deploy Governor implementation contract
CompoundGovernor _implementation = new CompoundGovernor();

bytes memory _initData = abi.encodeCall(
CompoundGovernor.initialize,
(
INITIAL_VOTING_DELAY,
INITIAL_VOTING_PERIOD,
INITIAL_PROPOSAL_THRESHOLD,
IVotes(COMP_TOKEN_ADDRESS),
INITIAL_QUORUM,
ICompoundTimelock(TIMELOCK_ADDRESS),
INITIAL_VOTE_EXTENSION,
_owner
)
);
TransparentUpgradeableProxy _proxy =
new TransparentUpgradeableProxy(address(_implementation), address(this), _initData);
_governor = CompoundGovernor(payable(address(_proxy)));

vm.stopBroadcast();
}
}

0 comments on commit 5309e98

Please sign in to comment.