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

Updated latest versions of OpenZeppelin contracts #7

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
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
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ clean :; forge clean

remove :; rm -rf .gitmodules && rm -rf .git/modules/* && rm -rf lib && touch .gitmodules && git add . && git commit -m "modules"

install :; forge install foundry-rs/forge-std --no-commit && forge install openzeppelin/openzeppelin-contracts@v4.8.3 --no-commit
install :; forge install foundry-rs/forge-std --no-commit && forge install openzeppelin/openzeppelin-contracts@v5.0.2 --no-commit

# Update Dependencies
update:; forge update
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ This is a section of the Cyfrin Foundry Solidity Course.

[One of my favorite articles on money-based voting being bad](https://vitalik.ca/general/2018/03/28/plutocracy.html)

> Note: If you install the most recent version of openzeppelin contracts, this codebase won't work! Be sure to install `v4.8.3` of openzeppelin. See the `Makefile` for more information.
> Note: If you install the most recent version of openzeppelin contracts, this codebase won't work! Be sure to install `v5.0.2` of openzeppelin. See the `Makefile` for more information.

- [Foundry DAO Governance](#foundry-dao-governance)
- [Getting Started](#getting-started)
Expand Down
2 changes: 1 addition & 1 deletion lib/openzeppelin-contracts
2 changes: 1 addition & 1 deletion src/Box.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pragma solidity ^0.8.0;

import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";

contract Box is Ownable {
contract Box is Ownable(msg.sender) {
uint256 private value;

// Emitted when the stored value changes
Expand Down
28 changes: 0 additions & 28 deletions src/GovToken.sol

This file was deleted.

25 changes: 25 additions & 0 deletions src/GovernanceToken.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// SPDX-License-Identifier: MIT
// Compatible with OpenZeppelin Contracts ^5.0.0
pragma solidity ^0.8.20;

import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {ERC20Permit, Nonces} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";
import {ERC20Votes} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol";

contract GovernanceToken is ERC20, ERC20Permit, ERC20Votes {
Copy link

Choose a reason for hiding this comment

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

@PatrickAlphaC @Akash-Kolekar - Can one of you please explain why we do this double inheritance, I've seen it before in the Proxy Lesson...

If GovernanceToken is extending / inheriting from ERC20Votes which inherits from ERC20 what's the need for the explicit inheritance of the ERC20 contract by the GovernanceToken contract?

Copy link
Member

Choose a reason for hiding this comment

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

It's a bit redundant yes! But we need it to tell solidity what functions we are overriding below.

Copy link

Choose a reason for hiding this comment

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

But doesn't it already know? At compile time shouldn't the solc
Compiler know this without the explicit inheritance in the Governance Token.

constructor() ERC20("GovernanceToken", "GT") ERC20Permit("GovernanceToken") {}

// The following functions are overrides required by Solidity.

function _update(address from, address to, uint256 value) internal override(ERC20, ERC20Votes) {
super._update(from, to, value);
}

function nonces(address owner) public view override(ERC20Permit, Nonces) returns (uint256) {
return super.nonces(owner);
}

function mint(address to, uint256 amount) public {
_mint(to, amount);
}
}
56 changes: 28 additions & 28 deletions src/MyGovernor.sol
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
pragma solidity ^0.8.20;

import {Governor} from "@openzeppelin/contracts/governance/Governor.sol";
import {GovernorSettings} from "@openzeppelin/contracts/governance/extensions/GovernorSettings.sol";
import {GovernorCountingSimple} from "@openzeppelin/contracts/governance/extensions/GovernorCountingSimple.sol";
import {GovernorVotes} from "@openzeppelin/contracts/governance/extensions/GovernorVotes.sol";
import {GovernorVotes, IVotes} from "@openzeppelin/contracts/governance/extensions/GovernorVotes.sol";
import {GovernorVotesQuorumFraction} from
"@openzeppelin/contracts/governance/extensions/GovernorVotesQuorumFraction.sol";
import {GovernorTimelockControl} from "@openzeppelin/contracts/governance/extensions/GovernorTimelockControl.sol";
import {TimelockController} from "@openzeppelin/contracts/governance/TimelockController.sol";

import {IVotes} from "@openzeppelin/contracts/governance/utils/IVotes.sol";
import {IGovernor} from "@openzeppelin/contracts/governance/IGovernor.sol";
import {
GovernorTimelockControl,
TimelockController
} from "@openzeppelin/contracts/governance/extensions/GovernorTimelockControl.sol";

contract MyGovernor is
Governor,
Expand All @@ -31,18 +30,18 @@ contract MyGovernor is

// The following functions are overrides required by Solidity.

function votingDelay() public view override(IGovernor, GovernorSettings) returns (uint256) {
function votingDelay() public view override(Governor, GovernorSettings) returns (uint256) {
return super.votingDelay();
}

function votingPeriod() public view override(IGovernor, GovernorSettings) returns (uint256) {
function votingPeriod() public view override(Governor, GovernorSettings) returns (uint256) {
return super.votingPeriod();
}

function quorum(uint256 blockNumber)
public
view
override(IGovernor, GovernorVotesQuorumFraction)
override(Governor, GovernorVotesQuorumFraction)
returns (uint256)
{
return super.quorum(blockNumber);
Expand All @@ -57,27 +56,37 @@ contract MyGovernor is
return super.state(proposalId);
}

function propose(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
string memory description
) public override(Governor, IGovernor) returns (uint256) {
return super.propose(targets, values, calldatas, description);
function proposalNeedsQueuing(uint256 proposalId)
public
view
override(Governor, GovernorTimelockControl)
returns (bool)
{
return super.proposalNeedsQueuing(proposalId);
}

function proposalThreshold() public view override(Governor, GovernorSettings) returns (uint256) {
return super.proposalThreshold();
}

function _execute(
function _queueOperations(
uint256 proposalId,
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) internal override(Governor, GovernorTimelockControl) returns (uint48) {
return super._queueOperations(proposalId, targets, values, calldatas, descriptionHash);
}

function _executeOperations(
uint256 proposalId,
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) internal override(Governor, GovernorTimelockControl) {
super._execute(proposalId, targets, values, calldatas, descriptionHash);
super._executeOperations(proposalId, targets, values, calldatas, descriptionHash);
}

function _cancel(
Expand All @@ -92,13 +101,4 @@ contract MyGovernor is
function _executor() internal view override(Governor, GovernorTimelockControl) returns (address) {
return super._executor();
}

function supportsInterface(bytes4 interfaceId)
public
view
override(Governor, GovernorTimelockControl)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
}
8 changes: 4 additions & 4 deletions test/MyGovernorTest.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ pragma solidity ^0.8.19;

import {Test, console} from "forge-std/Test.sol";
import {MyGovernor} from "../src/MyGovernor.sol";
import {GovToken} from "../src/GovToken.sol";
import {GovernanceToken} from "../src/GovernanceToken.sol";
import {TimeLock} from "../src/TimeLock.sol";
import {Box} from "../src/Box.sol";

contract MyGovernorTest is Test {
GovToken token;
GovernanceToken token;
TimeLock timelock;
MyGovernor governor;
Box box;
Expand All @@ -28,7 +28,7 @@ contract MyGovernorTest is Test {
address public constant VOTER = address(1);

function setUp() public {
token = new GovToken();
token = new GovernanceToken();
token.mint(VOTER, 100e18);

vm.prank(VOTER);
Expand All @@ -37,7 +37,7 @@ contract MyGovernorTest is Test {
governor = new MyGovernor(token, timelock);
bytes32 proposerRole = timelock.PROPOSER_ROLE();
bytes32 executorRole = timelock.EXECUTOR_ROLE();
bytes32 adminRole = timelock.TIMELOCK_ADMIN_ROLE();
bytes32 adminRole = timelock.DEFAULT_ADMIN_ROLE();

timelock.grantRole(proposerRole, address(governor));
timelock.grantRole(executorRole, address(0));
Expand Down