From 875a7af823abfb6abcf78ba19095d82801668c9a Mon Sep 17 00:00:00 2001 From: garyghayrat Date: Wed, 9 Oct 2024 13:22:37 -0400 Subject: [PATCH 1/7] Add `CompoundGovernorVotesUpgradeable` and `IComp` --- .../CompoundGovernorVotesUpgradeable.sol | 77 +++++++++++++++++++ contracts/interfaces/IComp.sol | 34 ++++++++ 2 files changed, 111 insertions(+) create mode 100644 contracts/extensions/CompoundGovernorVotesUpgradeable.sol create mode 100644 contracts/interfaces/IComp.sol diff --git a/contracts/extensions/CompoundGovernorVotesUpgradeable.sol b/contracts/extensions/CompoundGovernorVotesUpgradeable.sol new file mode 100644 index 0000000..77129e4 --- /dev/null +++ b/contracts/extensions/CompoundGovernorVotesUpgradeable.sol @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.26; + +import {GovernorUpgradeable} from "@openzeppelin/contracts-upgradeable/governance/GovernorUpgradeable.sol"; +import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol"; +import {Time} from "@openzeppelin/contracts/utils/types/Time.sol"; +import {IComp} from "contracts/interfaces/IComp.sol"; + +/// @title CompoundGovernorVotesUpgradeable +/// @author [ScopeLift](https://scopelift.co) +/// @notice Modified GovernorVotes contract that supports Compound's COMP token. +/// @custom:security-contact TODO: Add security contact +abstract contract CompoundGovernorVotesUpgradeable is Initializable, GovernorUpgradeable { + /// @custom:storage-location IComp:storage.CompoundGovernorVotes + struct CompoundGovernorVotesStorage { + IComp _token; + } + + // keccak256(abi.encode(uint256(keccak256("storage.CompoundGovernorVotes")) - 1)) & ~bytes32(uint256(0xff)) + bytes32 private constant CompoundGovernorVotesStorageLocation = + 0x69f1f297e68cd1b53f75e4e19d390fe2baecb721066d42c98913bf524d296400; + + function _getCompoundGovernorVotesStorage() private pure returns (CompoundGovernorVotesStorage storage $) { + assembly { + $.slot := CompoundGovernorVotesStorageLocation + } + } + + function __CompoundGovernorVotes_init(IComp tokenAddress) internal onlyInitializing { + __CompoundGovernorVotes_init_unchained(tokenAddress); + } + + function __CompoundGovernorVotes_init_unchained(IComp tokenAddress) internal onlyInitializing { + CompoundGovernorVotesStorage storage $ = _getCompoundGovernorVotesStorage(); + $._token = IComp(address(tokenAddress)); + } + + /// @notice Returns the IComp token used for governance. + /// @dev This function retrieves the token address from the contract's storage. + /// @return IComp The COMP token interface used for governance voting. + function token() public view virtual returns (IComp) { + CompoundGovernorVotesStorage storage $ = _getCompoundGovernorVotesStorage(); + return $._token; + } + + /// @notice This function implements the clock interface as specified in ERC-6372. + /// @dev Returns the current clock value used for governance voting. + /// @return uint48 The current block number cast to uint48. + function clock() public view virtual override returns (uint48) { + return Time.blockNumber(); + } + + /// @notice Returns a machine-readable description of the clock as specified in ERC-6372. + /// @dev This function provides information about the clock mode used for governance timing. + /// @return string A string describing the clock mode, indicating that block numbers are used + /// as the time measure, with the default starting point. + function CLOCK_MODE() public view virtual override returns (string memory) { + return "mode=blocknumber&from=default"; + } + + /// @notice Retrieves the voting weight for a specific account at a given timepoint. + /// @dev This function overrides the base _getVotes function to use Compound's getPriorVotes mechanism. + /// @param account The address of the account to check the voting weight for. + /// @param timepoint The block number at which to check the voting weight. + /// @param /*params*/ Unused parameter, kept for compatibility with the base function signature. + /// @return uint256 The voting weight of the account at the specified timepoint. + function _getVotes(address account, uint256 timepoint, bytes memory /*params*/ ) + internal + view + virtual + override + returns (uint256) + { + return token().getPriorVotes(account, timepoint); + } +} diff --git a/contracts/interfaces/IComp.sol b/contracts/interfaces/IComp.sol new file mode 100644 index 0000000..6723597 --- /dev/null +++ b/contracts/interfaces/IComp.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; + +interface IComp { + struct Checkpoint { + uint32 fromBlock; + uint96 votes; + } + + event Approval(address indexed owner, address indexed spender, uint256 amount); + event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate); + event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance); + event Transfer(address indexed from, address indexed to, uint256 amount); + + function DELEGATION_TYPEHASH() external view returns (bytes32); + function DOMAIN_TYPEHASH() external view returns (bytes32); + function allowance(address account, address spender) external view returns (uint256); + function approve(address spender, uint256 rawAmount) external returns (bool); + function balanceOf(address account) external view returns (uint256); + function checkpoints(address, uint32) external view returns (uint32 fromBlock, uint96 votes); + function decimals() external view returns (uint8); + function delegate(address delegatee) external; + function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external; + function delegates(address) external view returns (address); + function getCurrentVotes(address account) external view returns (uint96); + function getPriorVotes(address account, uint256 blockNumber) external view returns (uint96); + function name() external view returns (string memory); + function nonces(address) external view returns (uint256); + function numCheckpoints(address) external view returns (uint32); + function symbol() external view returns (string memory); + function totalSupply() external view returns (uint256); + function transfer(address dst, uint256 rawAmount) external returns (bool); + function transferFrom(address src, address dst, uint256 rawAmount) external returns (bool); +} From 6d5b5d30a74230b55aa13fa82ff9e92b98147fb1 Mon Sep 17 00:00:00 2001 From: garyghayrat Date: Wed, 9 Oct 2024 16:04:27 -0400 Subject: [PATCH 2/7] Add tests and misc --- .../CompoundGovernorVotesUpgradeable.sol | 18 +++--- contracts/interfaces/IComp.sol | 4 +- .../CompoundGovernorVotesUpgradeable.t.sol | 57 +++++++++++++++++++ script/CompoundGovernorConstants.sol | 24 ++++++++ 4 files changed, 92 insertions(+), 11 deletions(-) create mode 100644 contracts/test/CompoundGovernorVotesUpgradeable.t.sol diff --git a/contracts/extensions/CompoundGovernorVotesUpgradeable.sol b/contracts/extensions/CompoundGovernorVotesUpgradeable.sol index 77129e4..e4221da 100644 --- a/contracts/extensions/CompoundGovernorVotesUpgradeable.sol +++ b/contracts/extensions/CompoundGovernorVotesUpgradeable.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.26; +pragma solidity 0.8.26; import {GovernorUpgradeable} from "@openzeppelin/contracts-upgradeable/governance/GovernorUpgradeable.sol"; import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; @@ -27,13 +27,13 @@ abstract contract CompoundGovernorVotesUpgradeable is Initializable, GovernorUpg } } - function __CompoundGovernorVotes_init(IComp tokenAddress) internal onlyInitializing { - __CompoundGovernorVotes_init_unchained(tokenAddress); + function __CompoundGovernorVotes_init(IComp _tokenAddress) internal onlyInitializing { + __CompoundGovernorVotes_init_unchained(_tokenAddress); } - function __CompoundGovernorVotes_init_unchained(IComp tokenAddress) internal onlyInitializing { + function __CompoundGovernorVotes_init_unchained(IComp _tokenAddress) internal onlyInitializing { CompoundGovernorVotesStorage storage $ = _getCompoundGovernorVotesStorage(); - $._token = IComp(address(tokenAddress)); + $._token = IComp(address(_tokenAddress)); } /// @notice Returns the IComp token used for governance. @@ -61,17 +61,17 @@ abstract contract CompoundGovernorVotesUpgradeable is Initializable, GovernorUpg /// @notice Retrieves the voting weight for a specific account at a given timepoint. /// @dev This function overrides the base _getVotes function to use Compound's getPriorVotes mechanism. - /// @param account The address of the account to check the voting weight for. - /// @param timepoint The block number at which to check the voting weight. + /// @param _account The address of the account to check the voting weight for. + /// @param _timepoint The block number at which to check the voting weight. /// @param /*params*/ Unused parameter, kept for compatibility with the base function signature. /// @return uint256 The voting weight of the account at the specified timepoint. - function _getVotes(address account, uint256 timepoint, bytes memory /*params*/ ) + function _getVotes(address _account, uint256 _timepoint, bytes memory /*params*/ ) internal view virtual override returns (uint256) { - return token().getPriorVotes(account, timepoint); + return token().getPriorVotes(_account, _timepoint); } } diff --git a/contracts/interfaces/IComp.sol b/contracts/interfaces/IComp.sol index 6723597..1daf178 100644 --- a/contracts/interfaces/IComp.sol +++ b/contracts/interfaces/IComp.sol @@ -1,5 +1,5 @@ -// SPDX-License-Identifier: BSD-3-Clause -pragma solidity ^0.8.10; +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.26; interface IComp { struct Checkpoint { diff --git a/contracts/test/CompoundGovernorVotesUpgradeable.t.sol b/contracts/test/CompoundGovernorVotesUpgradeable.t.sol new file mode 100644 index 0000000..9c95f01 --- /dev/null +++ b/contracts/test/CompoundGovernorVotesUpgradeable.t.sol @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import {Test} from "forge-std/Test.sol"; +import {CompoundGovernorVotesUpgradeable} from "contracts/extensions/CompoundGovernorVotesUpgradeable.sol"; +import {CompoundGovernorConstants} from "script/CompoundGovernorConstants.sol"; +import {IComp} from "contracts/interfaces/IComp.sol"; + +contract CompoundGovernorVotesUpgradeableTestHarness is CompoundGovernorVotesUpgradeable { + function initialize(IComp _compToken) public initializer { + __CompoundGovernorVotes_init(_compToken); + } + + function COUNTING_MODE() external view override returns (string memory) {} + function _countVote(uint256 _proposalId, address _account, uint8 _support, uint256 _weight, bytes memory _params) + internal + override + {} + function _quorumReached(uint256 _proposalId) internal view override returns (bool) {} + function _voteSucceeded(uint256 _proposalId) internal view override returns (bool) {} + function hasVoted(uint256 _proposalId, address account) external view override returns (bool) {} + function quorum(uint256 _timepoint) public view override returns (uint256) {} + function votingDelay() public view override returns (uint256) {} + function votingPeriod() public view override returns (uint256) {} +} + +contract CompoundGovernorVotesUpgradeableTest is Test, CompoundGovernorConstants { + CompoundGovernorVotesUpgradeableTestHarness governorVotes; + + function setUp() public { + vm.createSelectFork(vm.envOr("RPC_URL", string("Please set RPC_URL in your .env file")), FORK_BLOCK); + governorVotes = new CompoundGovernorVotesUpgradeableTestHarness(); + governorVotes.initialize(IComp(COMP_TOKEN_ADDRESS)); + } + + function test_Initialize() public { + assertEq(address(governorVotes.token()), address(COMP_TOKEN_ADDRESS)); + } + + function test_Clock() public { + assertEq(governorVotes.clock(), block.number); + } + + function test_ClockMode() public { + assertEq(governorVotes.CLOCK_MODE(), "mode=blocknumber&from=default"); + } + + function testFuzz_GetVotes(uint256 _blockNumber) public { + _blockNumber = bound(_blockNumber, 0, FORK_BLOCK - 1); + for (uint256 i; i < _majorDelegates.length; i++) { + assertEq( + governorVotes.getVotes(_majorDelegates[i], _blockNumber), + IComp(COMP_TOKEN_ADDRESS).getPriorVotes(_majorDelegates[i], _blockNumber) + ); + } + } +} diff --git a/script/CompoundGovernorConstants.sol b/script/CompoundGovernorConstants.sol index a51ce8b..2714a60 100644 --- a/script/CompoundGovernorConstants.sol +++ b/script/CompoundGovernorConstants.sol @@ -22,4 +22,28 @@ contract CompoundGovernorConstants { // The fork block for testing uint256 FORK_BLOCK = 20_885_000; + + address[] public _majorDelegates; + + constructor() { + _majorDelegates = new address[](18); + _majorDelegates[0] = 0x1B686eE8E31c5959D9F5BBd8122a58682788eeaD; // L2BEAT + _majorDelegates[1] = 0xF4B0556B9B6F53E00A1FDD2b0478Ce841991D8fA; // olimpio + _majorDelegates[2] = 0x11cd09a0c5B1dc674615783b0772a9bFD53e3A8F; // Gauntlet + _majorDelegates[3] = 0xB933AEe47C438f22DE0747D57fc239FE37878Dd1; // Wintermute + _majorDelegates[4] = 0x0eB5B03c0303f2F47cD81d7BE4275AF8Ed347576; // Treasure + _majorDelegates[5] = 0xF92F185AbD9E00F56cb11B0b709029633d1E37B4; // + _majorDelegates[6] = 0x186e505097BFA1f3cF45c2C9D7a79dE6632C3cdc; + _majorDelegates[7] = 0x5663D01D8109DDFC8aACf09fBE51F2d341bb3643; + _majorDelegates[8] = 0x2ef27b114917dD53f8633440A7C0328fef132e2F; // MUX Protocol + _majorDelegates[9] = 0xE48C655276C23F1534AE2a87A2bf8A8A6585Df70; // ercwl + _majorDelegates[10] = 0x8A3e9846df0CDc723C06e4f0C642ffFF82b54610; + _majorDelegates[11] = 0xAD16ebE6FfC7d96624A380F394cD64395B0C6144; // DK (Premia) + _majorDelegates[12] = 0xA5dF0cf3F95C6cd97d998b9D990a86864095d9b0; // Blockworks Research + _majorDelegates[13] = 0x839395e20bbB182fa440d08F850E6c7A8f6F0780; // Griff Green + _majorDelegates[14] = 0x2e3BEf6830Ae84bb4225D318F9f61B6b88C147bF; // Camelot + _majorDelegates[15] = 0x8F73bE66CA8c79382f72139be03746343Bf5Faa0; // mihal.eth + _majorDelegates[16] = 0xb5B069370Ef24BC67F114e185D185063CE3479f8; // Frisson + _majorDelegates[17] = 0xdb5781a835b60110298fF7205D8ef9678Ff1f800; // yoav.eth + } } From 7dc39dffb2b9a51fdde80c57689d193e9adc067d Mon Sep 17 00:00:00 2001 From: garyghayrat Date: Fri, 11 Oct 2024 09:52:30 -0400 Subject: [PATCH 3/7] Make tests `view` --- contracts/test/CompoundGovernorVotesUpgradeable.t.sol | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/contracts/test/CompoundGovernorVotesUpgradeable.t.sol b/contracts/test/CompoundGovernorVotesUpgradeable.t.sol index 9c95f01..6610608 100644 --- a/contracts/test/CompoundGovernorVotesUpgradeable.t.sol +++ b/contracts/test/CompoundGovernorVotesUpgradeable.t.sol @@ -33,19 +33,19 @@ contract CompoundGovernorVotesUpgradeableTest is Test, CompoundGovernorConstants governorVotes.initialize(IComp(COMP_TOKEN_ADDRESS)); } - function test_Initialize() public { + function test_Initialize() public view { assertEq(address(governorVotes.token()), address(COMP_TOKEN_ADDRESS)); } - function test_Clock() public { + function test_Clock() public view { assertEq(governorVotes.clock(), block.number); } - function test_ClockMode() public { + function test_ClockMode() public view { assertEq(governorVotes.CLOCK_MODE(), "mode=blocknumber&from=default"); } - function testFuzz_GetVotes(uint256 _blockNumber) public { + function testFuzz_GetVotes(uint256 _blockNumber) public view { _blockNumber = bound(_blockNumber, 0, FORK_BLOCK - 1); for (uint256 i; i < _majorDelegates.length; i++) { assertEq( From 3f7980b14792fad8659602731868aa33aed5fe1b Mon Sep 17 00:00:00 2001 From: garyghayrat Date: Fri, 11 Oct 2024 11:19:04 -0400 Subject: [PATCH 4/7] Rename and inherit contract --- contracts/CompoundGovernor.sol | 11 ++++---- ...e.sol => GovernorVotesCompUpgradeable.sol} | 26 +++++++++---------- ...sol => GovernorVotesCompUpgradeable.t.sol} | 12 ++++----- script/DeployCompoundGovernor.s.sol | 4 +-- 4 files changed, 26 insertions(+), 27 deletions(-) rename contracts/extensions/{CompoundGovernorVotesUpgradeable.sol => GovernorVotesCompUpgradeable.sol} (73%) rename contracts/test/{CompoundGovernorVotesUpgradeable.t.sol => GovernorVotesCompUpgradeable.t.sol} (81%) diff --git a/contracts/CompoundGovernor.sol b/contracts/CompoundGovernor.sol index 41c932f..7bb0cbb 100644 --- a/contracts/CompoundGovernor.sol +++ b/contracts/CompoundGovernor.sol @@ -3,8 +3,7 @@ pragma solidity 0.8.26; 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 {GovernorVotesCompUpgradeable} from "contracts/extensions/GovernorVotesCompUpgradeable.sol"; import {GovernorSettableFixedQuorumUpgradeable} from "contracts/extensions/GovernorSettableFixedQuorumUpgradeable.sol"; import {GovernorCountingFractionalUpgradeable} from "@openzeppelin/contracts-upgradeable/governance/extensions/GovernorCountingFractionalUpgradeable.sol"; @@ -16,7 +15,7 @@ import {GovernorSettingsUpgradeable} from 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 {IComp} from "contracts/interfaces/IComp.sol"; import {Address} from "@openzeppelin/contracts/utils/Address.sol"; /// @title CompoundGovernor @@ -25,7 +24,7 @@ import {Address} from "@openzeppelin/contracts/utils/Address.sol"; /// @custom:security-contact TODO: Add security contact contract CompoundGovernor is Initializable, - GovernorVotesUpgradeable, + GovernorVotesCompUpgradeable, GovernorTimelockCompoundUpgradeable, GovernorSettingsUpgradeable, GovernorCountingFractionalUpgradeable, @@ -51,7 +50,7 @@ contract CompoundGovernor is uint48 _initialVotingDelay, uint32 _initialVotingPeriod, uint256 _initialProposalThreshold, - IVotes _compAddress, + IComp _compAddress, uint256 _quorumVotes, ICompoundTimelock _timelockAddress, uint48 _initialVoteExtension, @@ -59,7 +58,7 @@ contract CompoundGovernor is ) public initializer { __Governor_init("Compound Governor"); __GovernorSettings_init(_initialVotingDelay, _initialVotingPeriod, _initialProposalThreshold); - __GovernorVotes_init(_compAddress); + __GovernorVotesComp_init(_compAddress); __GovernorTimelockCompound_init(_timelockAddress); __GovernorPreventLateQuorum_init(_initialVoteExtension); __GovernorSettableFixedQuorum_init(_quorumVotes); diff --git a/contracts/extensions/CompoundGovernorVotesUpgradeable.sol b/contracts/extensions/GovernorVotesCompUpgradeable.sol similarity index 73% rename from contracts/extensions/CompoundGovernorVotesUpgradeable.sol rename to contracts/extensions/GovernorVotesCompUpgradeable.sol index e4221da..a11c271 100644 --- a/contracts/extensions/CompoundGovernorVotesUpgradeable.sol +++ b/contracts/extensions/GovernorVotesCompUpgradeable.sol @@ -7,32 +7,32 @@ import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol"; import {Time} from "@openzeppelin/contracts/utils/types/Time.sol"; import {IComp} from "contracts/interfaces/IComp.sol"; -/// @title CompoundGovernorVotesUpgradeable +/// @title GovernorVotesCompUpgradeable /// @author [ScopeLift](https://scopelift.co) /// @notice Modified GovernorVotes contract that supports Compound's COMP token. /// @custom:security-contact TODO: Add security contact -abstract contract CompoundGovernorVotesUpgradeable is Initializable, GovernorUpgradeable { - /// @custom:storage-location IComp:storage.CompoundGovernorVotes - struct CompoundGovernorVotesStorage { +abstract contract GovernorVotesCompUpgradeable is Initializable, GovernorUpgradeable { + /// @custom:storage-location IComp:storage.GovernorVotesComp + struct GovernorVotesCompStorage { IComp _token; } - // keccak256(abi.encode(uint256(keccak256("storage.CompoundGovernorVotes")) - 1)) & ~bytes32(uint256(0xff)) - bytes32 private constant CompoundGovernorVotesStorageLocation = + // keccak256(abi.encode(uint256(keccak256("storage.GovernorVotesComp")) - 1)) & ~bytes32(uint256(0xff)) + bytes32 private constant GovernorVotesCompStorageLocation = 0x69f1f297e68cd1b53f75e4e19d390fe2baecb721066d42c98913bf524d296400; - function _getCompoundGovernorVotesStorage() private pure returns (CompoundGovernorVotesStorage storage $) { + function _getGovernorVotesCompStorage() private pure returns (GovernorVotesCompStorage storage $) { assembly { - $.slot := CompoundGovernorVotesStorageLocation + $.slot := GovernorVotesCompStorageLocation } } - function __CompoundGovernorVotes_init(IComp _tokenAddress) internal onlyInitializing { - __CompoundGovernorVotes_init_unchained(_tokenAddress); + function __GovernorVotesComp_init(IComp _tokenAddress) internal onlyInitializing { + __GovernorVotesComp_init_unchained(_tokenAddress); } - function __CompoundGovernorVotes_init_unchained(IComp _tokenAddress) internal onlyInitializing { - CompoundGovernorVotesStorage storage $ = _getCompoundGovernorVotesStorage(); + function __GovernorVotesComp_init_unchained(IComp _tokenAddress) internal onlyInitializing { + GovernorVotesCompStorage storage $ = _getGovernorVotesCompStorage(); $._token = IComp(address(_tokenAddress)); } @@ -40,7 +40,7 @@ abstract contract CompoundGovernorVotesUpgradeable is Initializable, GovernorUpg /// @dev This function retrieves the token address from the contract's storage. /// @return IComp The COMP token interface used for governance voting. function token() public view virtual returns (IComp) { - CompoundGovernorVotesStorage storage $ = _getCompoundGovernorVotesStorage(); + GovernorVotesCompStorage storage $ = _getGovernorVotesCompStorage(); return $._token; } diff --git a/contracts/test/CompoundGovernorVotesUpgradeable.t.sol b/contracts/test/GovernorVotesCompUpgradeable.t.sol similarity index 81% rename from contracts/test/CompoundGovernorVotesUpgradeable.t.sol rename to contracts/test/GovernorVotesCompUpgradeable.t.sol index 6610608..273d005 100644 --- a/contracts/test/CompoundGovernorVotesUpgradeable.t.sol +++ b/contracts/test/GovernorVotesCompUpgradeable.t.sol @@ -2,13 +2,13 @@ pragma solidity 0.8.26; import {Test} from "forge-std/Test.sol"; -import {CompoundGovernorVotesUpgradeable} from "contracts/extensions/CompoundGovernorVotesUpgradeable.sol"; +import {GovernorVotesCompUpgradeable} from "contracts/extensions/GovernorVotesCompUpgradeable.sol"; import {CompoundGovernorConstants} from "script/CompoundGovernorConstants.sol"; import {IComp} from "contracts/interfaces/IComp.sol"; -contract CompoundGovernorVotesUpgradeableTestHarness is CompoundGovernorVotesUpgradeable { +contract GovernorVotesCompUpgradeableTestHarness is GovernorVotesCompUpgradeable { function initialize(IComp _compToken) public initializer { - __CompoundGovernorVotes_init(_compToken); + __GovernorVotesComp_init(_compToken); } function COUNTING_MODE() external view override returns (string memory) {} @@ -24,12 +24,12 @@ contract CompoundGovernorVotesUpgradeableTestHarness is CompoundGovernorVotesUpg function votingPeriod() public view override returns (uint256) {} } -contract CompoundGovernorVotesUpgradeableTest is Test, CompoundGovernorConstants { - CompoundGovernorVotesUpgradeableTestHarness governorVotes; +contract GovernorVotesCompUpgradeableTest is Test, CompoundGovernorConstants { + GovernorVotesCompUpgradeableTestHarness governorVotes; function setUp() public { vm.createSelectFork(vm.envOr("RPC_URL", string("Please set RPC_URL in your .env file")), FORK_BLOCK); - governorVotes = new CompoundGovernorVotesUpgradeableTestHarness(); + governorVotes = new GovernorVotesCompUpgradeableTestHarness(); governorVotes.initialize(IComp(COMP_TOKEN_ADDRESS)); } diff --git a/script/DeployCompoundGovernor.s.sol b/script/DeployCompoundGovernor.s.sol index a25bc1e..3b4783c 100644 --- a/script/DeployCompoundGovernor.s.sol +++ b/script/DeployCompoundGovernor.s.sol @@ -5,7 +5,7 @@ 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 {IComp} from "contracts/interfaces/IComp.sol"; import {ICompoundTimelock} from "@openzeppelin/contracts/vendor/compound/ICompoundTimelock.sol"; import {CompoundGovernor} from "contracts/CompoundGovernor.sol"; import {CompoundGovernorConstants} from "script/CompoundGovernorConstants.sol"; @@ -33,7 +33,7 @@ contract DeployCompoundGovernor is Script, CompoundGovernorConstants { INITIAL_VOTING_DELAY, INITIAL_VOTING_PERIOD, INITIAL_PROPOSAL_THRESHOLD, - IVotes(COMP_TOKEN_ADDRESS), + IComp(COMP_TOKEN_ADDRESS), INITIAL_QUORUM, ICompoundTimelock(TIMELOCK_ADDRESS), INITIAL_VOTE_EXTENSION, From 7779685109e3f47bbdf3902134472bc72e4031c9 Mon Sep 17 00:00:00 2001 From: garyghayrat Date: Fri, 11 Oct 2024 11:20:41 -0400 Subject: [PATCH 5/7] Update storage location --- contracts/extensions/GovernorVotesCompUpgradeable.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/extensions/GovernorVotesCompUpgradeable.sol b/contracts/extensions/GovernorVotesCompUpgradeable.sol index a11c271..3268d39 100644 --- a/contracts/extensions/GovernorVotesCompUpgradeable.sol +++ b/contracts/extensions/GovernorVotesCompUpgradeable.sol @@ -19,7 +19,7 @@ abstract contract GovernorVotesCompUpgradeable is Initializable, GovernorUpgrade // keccak256(abi.encode(uint256(keccak256("storage.GovernorVotesComp")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant GovernorVotesCompStorageLocation = - 0x69f1f297e68cd1b53f75e4e19d390fe2baecb721066d42c98913bf524d296400; + 0x2130f92f3b57a0ca0ff53b681825494ca70980d3b0ddffac97113db00028b600; function _getGovernorVotesCompStorage() private pure returns (GovernorVotesCompStorage storage $) { assembly { From 7d6d4bc20016a85f4de2fc7699b4fe1c2edc086b Mon Sep 17 00:00:00 2001 From: garyghayrat Date: Fri, 11 Oct 2024 13:35:08 -0400 Subject: [PATCH 6/7] Make test names descriptive --- contracts/test/GovernorVotesCompUpgradeable.t.sol | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/contracts/test/GovernorVotesCompUpgradeable.t.sol b/contracts/test/GovernorVotesCompUpgradeable.t.sol index 273d005..a0615a3 100644 --- a/contracts/test/GovernorVotesCompUpgradeable.t.sol +++ b/contracts/test/GovernorVotesCompUpgradeable.t.sol @@ -15,6 +15,7 @@ contract GovernorVotesCompUpgradeableTestHarness is GovernorVotesCompUpgradeable function _countVote(uint256 _proposalId, address _account, uint8 _support, uint256 _weight, bytes memory _params) internal override + returns (uint256) {} function _quorumReached(uint256 _proposalId) internal view override returns (bool) {} function _voteSucceeded(uint256 _proposalId) internal view override returns (bool) {} @@ -37,15 +38,15 @@ contract GovernorVotesCompUpgradeableTest is Test, CompoundGovernorConstants { assertEq(address(governorVotes.token()), address(COMP_TOKEN_ADDRESS)); } - function test_Clock() public view { + function test_ReturnsBlockNumberAsClock() public view { assertEq(governorVotes.clock(), block.number); } - function test_ClockMode() public view { + function test_ReturnsBlockNumberAsDefaultClockMode() public view { assertEq(governorVotes.CLOCK_MODE(), "mode=blocknumber&from=default"); } - function testFuzz_GetVotes(uint256 _blockNumber) public view { + function testFuzz_ReturnsCorrectVotes(uint256 _blockNumber) public view { _blockNumber = bound(_blockNumber, 0, FORK_BLOCK - 1); for (uint256 i; i < _majorDelegates.length; i++) { assertEq( From 8d5ee4c04af70d0ab89b38ead5a53bcc3c0f492f Mon Sep 17 00:00:00 2001 From: garyghayrat Date: Mon, 14 Oct 2024 12:21:13 -0400 Subject: [PATCH 7/7] Update natspec --- contracts/extensions/GovernorVotesCompUpgradeable.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/extensions/GovernorVotesCompUpgradeable.sol b/contracts/extensions/GovernorVotesCompUpgradeable.sol index 3268d39..1ecbb8b 100644 --- a/contracts/extensions/GovernorVotesCompUpgradeable.sol +++ b/contracts/extensions/GovernorVotesCompUpgradeable.sol @@ -62,7 +62,7 @@ abstract contract GovernorVotesCompUpgradeable is Initializable, GovernorUpgrade /// @notice Retrieves the voting weight for a specific account at a given timepoint. /// @dev This function overrides the base _getVotes function to use Compound's getPriorVotes mechanism. /// @param _account The address of the account to check the voting weight for. - /// @param _timepoint The block number at which to check the voting weight. + /// @param _timepoint The timepoint at which to check the voting weight. /// @param /*params*/ Unused parameter, kept for compatibility with the base function signature. /// @return uint256 The voting weight of the account at the specified timepoint. function _getVotes(address _account, uint256 _timepoint, bytes memory /*params*/ )