Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added test framework with minimal deploy script #17

Merged
merged 3 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hey @jferas how confident are we that these are the constants we're going live with? should we put a TODO here (or better, an issue to verify these initialization params)?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a TODO: 5c79b52

Also added an issue: #19

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(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it possible to avoid setting a PK in the env? Would prefer to let foundry manage the wallet instead. We run across this often, and i remember there's a limitation with calling scripts in tests. maybe this is something we can create an issue for.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added an issue: #18

"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();
}
}
Loading