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

Voting tokens #2

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
17 changes: 17 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"root": true,
"overrides": [
{
"files": ["src/**/*.ts", "test/**/*.ts", "./*.ts"],
"extends": ["@zero-tech/eslint-config-cpt/node-ts/.eslintrc.json"],
"rules": {
"no-unused-expressions": "off",
"no-console": "off",
"no-shadow": "warn",
"@typescript-eslint/no-shadow": "warn",
"no-invalid-this": "off"
// "@typescript-eslint/no-unused-vars": "off" // For debugging
}
}
]
}
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
node_modules
.env
*.env
coverage
coverage.json
typechain
typechain-types
.idea
.vscode
dist
bin

# Hardhat files
/cache
Expand Down
3 changes: 1 addition & 2 deletions contracts/ZDAO.sol
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ contract ZDAO is
return super._executor();
}

/**
/**
* @notice Returns the proposal deadline in blocks.
* @param proposalId The ID of the proposal.
* @return The block number when voting ends.
Expand Down Expand Up @@ -196,7 +196,6 @@ contract ZDAO is
return super._castVote(proposalId, account, support, reason, params);
}


/**
* @notice Checks if a given interface is supported.
* @param interfaceId The interface identifier.
Expand Down
21 changes: 9 additions & 12 deletions contracts/mock/MockERC20Votes.sol
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.24;

import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol";
import "../votingTokens/ZeroVotingERC20.sol";

contract MockERC20Votes is Ownable, ERC20Votes {
///Test token, don't deploy
constructor(string memory name, string memory symbol)
ERC20(name, symbol)
ERC20Permit(name) // Initialize ERC20Permit with the token name
contract MockERC20Votes is ZeroVotingERC20 {
// Test token, don't deploy
constructor(
string memory name,
string memory symbol,
address deployer
)
ZeroVotingERC20(name, symbol, deployer)
{}

// Mint function with onlyOwner modifier
function mint(address to, uint256 amount) public onlyOwner {
_mint(to, amount);
}
}
23 changes: 11 additions & 12 deletions contracts/mock/MockERC721Votes.sol
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Votes.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "../votingTokens/ZeroVotingERC721.sol";


/**
* @title MockERC721Votes
* @dev ERC721 token with governance voting capabilities using OpenZeppelin's ERC721Votes.
*/
contract MockERC721Votes is ERC721Votes, Ownable {

constructor() ERC721("MockERC721Votes", "M721V") EIP712("name", "version"){}
contract MockERC721Votes is ZeroVotingERC721 {

/**
* @dev Mint a new token to a specific address.
* @param to The address to mint the token to.
*/
function mint(address to, uint id) external onlyOwner {
_safeMint(to, id);
}
constructor(
string memory name,
string memory symbol,
string memory version,
address deployer
)
ZeroVotingERC721 (name, symbol, version, deployer)
{}
}
26 changes: 26 additions & 0 deletions contracts/votingTokens/IZeroVotingERC20.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/access/IAccessControl.sol";

/**
MichaelKorchagin marked this conversation as resolved.
Show resolved Hide resolved
* @title Interface for ZeroVotingERC20 contract
*/
interface IZeroVotingERC20 is IERC20, IERC20Permit, IAccessControl {

/**
* @dev Burns a specified amount of tokens from the sender's account.
* @param account The account from which tokens will be burned.
* @param amount The amount of tokens to burn.
*/
function burn(address account, uint256 amount) external;

/**
* @dev Mints a specified amount of tokens to a specified account.
* @param account The address to receive the minted tokens.
* @param amount The amount of tokens to mint.
*/
function mint(address account, uint256 amount) external;
}
45 changes: 45 additions & 0 deletions contracts/votingTokens/IZeroVotingERC721.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/access/IAccessControl.sol";
import "@openzeppelin/contracts/utils/introspection/IERC165.sol";

/**
* @title ZeroVotingERC721 Interface
*/
interface IZeroVotingERC721 {
/**
* @dev Emitted when a new token is minted.
* @param to The address that received the minted token.
* @param tokenId The ID of the minted token.
*/
event Mint(address indexed to, uint256 indexed tokenId);

/**
* @dev Emitted when a token is burned.
* @param owner The address that owned the burned token.
* @param tokenId The ID of the burned token.
*/
event Burn(address indexed owner, uint256 indexed tokenId);

/**
* @dev External mint function. Mints a new token to a specified address.
* @param to The address that will receive the minted token.
* @param tokenId The token ID for the newly minted token.
*/
function mint(address to, uint256 tokenId) external;

/**
* @dev External burn function. Burns a token for a specified address.
* @param tokenId The token ID of the token to burn.
*/
function burn(uint256 tokenId) external;

/**
* @dev Overridden function to support the interfaces of ERC721 and AccessControl.
* @param interfaceId The interface identifier to check.
* @return True if the contract supports the given interface.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
120 changes: 120 additions & 0 deletions contracts/votingTokens/ZeroVotingERC20.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
MichaelKorchagin marked this conversation as resolved.
Show resolved Hide resolved

import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";
MichaelKorchagin marked this conversation as resolved.
Show resolved Hide resolved
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
import "./IZeroVotingERC20.sol";

/**
MichaelKorchagin marked this conversation as resolved.
Show resolved Hide resolved
* Throw this error if someone submits a zero token burn address.
* @param to address to send the transaction.
*/
error InvalidBurnAddress(address to);

contract ZeroVotingERC20 is ERC20, ERC20Permit, ERC20Votes, AccessControl, IZeroVotingERC20 {
MichaelKorchagin marked this conversation as resolved.
Show resolved Hide resolved

bytes32 public constant DEFAULT_ADMIN_ROLE_PUBLIC = DEFAULT_ADMIN_ROLE;
MichaelKorchagin marked this conversation as resolved.
Show resolved Hide resolved
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE");

/**
* @dev Initializes the token with name and symbol, also sets up ERC20Permit and ownership.
* @param name The name of the ERC20 token.
* @param symbol The symbol of the ERC20 token.
*/
constructor(
string memory name,
string memory symbol,
address deployer
MichaelKorchagin marked this conversation as resolved.
Show resolved Hide resolved
)
ERC20(name, symbol)
ERC20Permit(name)
AccessControl()
{
// temporary TODO: decide, who gets the roles
MichaelKorchagin marked this conversation as resolved.
Show resolved Hide resolved
_setupRole(DEFAULT_ADMIN_ROLE, deployer);
_setupRole(BURNER_ROLE, deployer);
_setupRole(MINTER_ROLE, deployer);
}

/**
* @dev External burn function. Burns a specified amount of tokens from the sender account.
* @param account Account where tokens need to be burned.
* @param amount The amount of tokens to burn.
*/
function burn(
address account,
uint256 amount
) external onlyRole(BURNER_ROLE) {
_burn(
account,
amount
);
}

/**
* @dev Internal burn function overriding ERC20 and ERC20Votes.
* @param account Account where tokens need to be burned.
* @param amount The amount of tokens to burn.
*/
function _burn(
address account,
uint256 amount
) internal override (ERC20, ERC20Votes) {
super._burn(
account,
amount
);
}

/**
* @dev External mint function. Mints a specified amount of tokens to a specified account.
* @param account The address that will receive the minted tokens.
* @param amount The amount of tokens to mint to the specified account.
*/
function mint(
address account,
uint256 amount
) external onlyRole(MINTER_ROLE) {
_mint(
account,
amount
);
}

/**
* @dev Internal mint function overriding ERC20 and ERC20Votes.
* @param account The address that will receive the minted tokens.
* @param amount The amount of tokens to mint to the specified account.
*/
function _mint(
address account,
uint256 amount
) internal override (ERC20, ERC20Votes) {
super._mint(
account,
amount
);
}

/**
* @dev Internal function afterTokenTransfer overriding ERC20 and ERC20Votes.
* @param from The address sending the tokens.
* @param to The address receiving the tokens.
* @param amount The amount of tokens being transferred.
*/
function _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal override (ERC20, ERC20Votes) {
super._afterTokenTransfer(
from,
to,
amount
);
}
}
Loading