Skip to content

Commit

Permalink
First pass on CompoundGovernor (#16)
Browse files Browse the repository at this point in the history
* forge install: openzeppelin-contracts-upgradeable

v5.0.2

* Create initial basic governor

* Line break fix

* Inheritance order fix

* Inheritdoc updates

* Fix eslint issue in lib directory

* Switch to using GovernorTimelockCompoundUpgradeable

* Fixed _executor function
  • Loading branch information
jferas authored and wildmolasses committed Nov 1, 2024
1 parent b7fbd77 commit 9302835
Show file tree
Hide file tree
Showing 7 changed files with 223 additions and 12 deletions.
3 changes: 2 additions & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ node_modules
artifacts
cache
coverage
typechain-types
typechain-types
lib
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[submodule "lib/forge-std"]
path = lib/forge-std
url = https://github.com/foundry-rs/forge-std
[submodule "lib/openzeppelin-contracts-upgradeable"]
path = lib/openzeppelin-contracts-upgradeable
url = https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable
186 changes: 183 additions & 3 deletions contracts/CompoundGovernor.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,185 @@
// SPDX-License-Identifier: BSD-3-Clause
pragma solidity 0.8.18;
pragma solidity 0.8.26;

// TODO: Implement new governance contract for Compound. This is just a placeholder to satisfy "forge fmt".
contract CompoundGovernor {}
import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import {GovernorUpgradeable} from "@openzeppelin/contracts-upgradeable/governance/GovernorUpgradeable.sol";
import {GovernorVotesUpgradeable} from
"@openzeppelin/contracts-upgradeable/governance/extensions/GovernorVotesUpgradeable.sol";
import {GovernorCountingSimpleUpgradeable} from
"@openzeppelin/contracts-upgradeable/governance/extensions/GovernorCountingSimpleUpgradeable.sol";
import {GovernorTimelockCompoundUpgradeable} from
"@openzeppelin/contracts-upgradeable/governance/extensions/GovernorTimelockCompoundUpgradeable.sol";
import {ICompoundTimelock} from "@openzeppelin/contracts/vendor/compound/ICompoundTimelock.sol";
import {GovernorSettingsUpgradeable} from
"@openzeppelin/contracts-upgradeable/governance/extensions/GovernorSettingsUpgradeable.sol";
import {GovernorPreventLateQuorumUpgradeable} from
"@openzeppelin/contracts-upgradeable/governance/extensions/GovernorPreventLateQuorumUpgradeable.sol";
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {IVotes} from "@openzeppelin/contracts/governance/utils/IVotes.sol";
import {Address} from "@openzeppelin/contracts/utils/Address.sol";

/// @title CompoundGovernor
/// @author [ScopeLift](https://scopelift.co)
/// @notice A governance contract for the Compound DAO.
/// @custom:security-contact TODO: Add security contact
contract CompoundGovernor is
Initializable,
GovernorVotesUpgradeable,
GovernorTimelockCompoundUpgradeable,
GovernorSettingsUpgradeable,
GovernorCountingSimpleUpgradeable,
GovernorPreventLateQuorumUpgradeable,
OwnableUpgradeable
{
/// @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

/// @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 _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,
ICompoundTimelock _timelockAddress,
uint48 _initialVoteExtension,
address _initialOwner
) public initializer {
__Governor_init(_name);
__GovernorSettings_init(_initialVotingDelay, _initialVotingPeriod, _initialProposalThreshold);
__GovernorVotes_init(_compAddress);
__GovernorTimelockCompound_init(_timelockAddress);
__GovernorPreventLateQuorum_init(_initialVoteExtension);
__Ownable_init(_initialOwner);
}

/// @inheritdoc GovernorTimelockCompoundUpgradeable
/// @dev We override this function to resolve ambiguity between inherited contracts.
function _cancel(
address[] memory _targets,
uint256[] memory _values,
bytes[] memory _calldatas,
bytes32 _descriptionHash
) internal virtual override(GovernorUpgradeable, GovernorTimelockCompoundUpgradeable) returns (uint256) {
return GovernorTimelockCompoundUpgradeable._cancel(_targets, _values, _calldatas, _descriptionHash);
}

/// @inheritdoc GovernorPreventLateQuorumUpgradeable
/// @dev We override this function to resolve ambiguity between inherited contracts.
function _castVote(
uint256 _proposalId,
address _account,
uint8 _support,
string memory _reason,
bytes memory _params
) internal virtual override(GovernorUpgradeable, GovernorPreventLateQuorumUpgradeable) returns (uint256) {
return GovernorPreventLateQuorumUpgradeable._castVote(_proposalId, _account, _support, _reason, _params);
}

/// @inheritdoc GovernorTimelockCompoundUpgradeable
/// @dev We override this function to resolve ambiguity between inherited contracts.
function _executeOperations(
uint256 _proposalId,
address[] memory _targets,
uint256[] memory _values,
bytes[] memory _calldatas,
bytes32 _descriptionHash
) internal virtual override(GovernorUpgradeable, GovernorTimelockCompoundUpgradeable) {
return GovernorTimelockCompoundUpgradeable._executeOperations(
_proposalId, _targets, _values, _calldatas, _descriptionHash
);
}

/// @inheritdoc GovernorTimelockCompoundUpgradeable
function _executor()
internal
view
override(GovernorUpgradeable, GovernorTimelockCompoundUpgradeable)
returns (address)
{
return GovernorTimelockCompoundUpgradeable._executor();
}

/// @inheritdoc GovernorTimelockCompoundUpgradeable
/// @dev We override this function to resolve ambiguity between inherited contracts.
function _queueOperations(
uint256 _proposalId,
address[] memory _targets,
uint256[] memory _values,
bytes[] memory _calldatas,
bytes32 _descriptionHash
) internal virtual override(GovernorUpgradeable, GovernorTimelockCompoundUpgradeable) returns (uint48) {
return GovernorTimelockCompoundUpgradeable._queueOperations(
_proposalId, _targets, _values, _calldatas, _descriptionHash
);
}

/// @inheritdoc GovernorPreventLateQuorumUpgradeable
/// @dev We override this function to resolve ambiguity between inherited contracts.
function proposalDeadline(uint256 _proposalId)
public
view
virtual
override(GovernorPreventLateQuorumUpgradeable, GovernorUpgradeable)
returns (uint256)
{
return GovernorPreventLateQuorumUpgradeable.proposalDeadline(_proposalId);
}

/// @inheritdoc GovernorTimelockCompoundUpgradeable
/// @dev We override this function to resolve ambiguity between inherited contracts.
function proposalNeedsQueuing(uint256 _proposalId)
public
view
virtual
override(GovernorTimelockCompoundUpgradeable, GovernorUpgradeable)
returns (bool)
{
return GovernorTimelockCompoundUpgradeable.proposalNeedsQueuing(_proposalId);
}

/// @inheritdoc GovernorSettingsUpgradeable
/// @dev We override this function to resolve ambiguity between inherited contracts.
function proposalThreshold()
public
view
virtual
override(GovernorSettingsUpgradeable, GovernorUpgradeable)
returns (uint256)
{
return GovernorSettingsUpgradeable.proposalThreshold();
}

/// @inheritdoc GovernorTimelockCompoundUpgradeable
/// @dev We override this function to resolve ambiguity between inherited contracts.
function state(uint256 _proposalId)
public
view
virtual
override(GovernorUpgradeable, GovernorTimelockCompoundUpgradeable)
returns (ProposalState)
{
return GovernorTimelockCompoundUpgradeable.state(_proposalId);
}

/// @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) {
return quorumVotes;
}
}
2 changes: 1 addition & 1 deletion contracts/test/CompoundGovernor.t.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: BSD-3-Clause
pragma solidity 0.8.18;
pragma solidity 0.8.26;

import {Test, console2} from "forge-std/Test.sol";

Expand Down
6 changes: 5 additions & 1 deletion foundry.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
[profile.default]
remappings = [
"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
"@openzeppelin/contracts/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/"
]
src = 'contracts'
out = 'out'
libs = ['node_modules', 'lib']
Expand All @@ -7,7 +11,7 @@
evm_version = "shanghai"
optimizer = true
optimizer_runs = 10_000_000
solc_version = "0.8.18"
solc_version = "0.8.26"
verbosity = 3

[profile.ci]
Expand Down
34 changes: 28 additions & 6 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,35 @@ dotEnvConfig();

const config: HardhatUserConfig = {
solidity: {
version: "0.8.18",
settings: {
optimizer: {
enabled: true,
runs: 200,
compilers: [
{
version: "0.8.18",
settings: {
optimizer: {
enabled: true,
runs: 200,
},
},
},
},
{
version: "0.8.20",
settings: {
optimizer: {
enabled: true,
runs: 200,
},
},
},
{
version: "0.8.26",
settings: {
optimizer: {
enabled: true,
runs: 200,
},
},
},
],
},
networks: {
mainnet: {
Expand Down
1 change: 1 addition & 0 deletions lib/openzeppelin-contracts-upgradeable

0 comments on commit 9302835

Please sign in to comment.