Hereâs my version of the contract. Iâve edited out all the comments for ease of reading. It differs to Filipâs version in two details.
One: I hard-coded the cap, because I donât know how to add arguments of the constructor when deploying (I kept on getting an error). If anyone can help me there Iâd much appreciate it.
And two: Instead of modifying the _beforeTokenTransfer() function with this code
if (from == address(0)) {
require(ERC20.totalSupply() + amount <= cap(), "ERC20Capped: cap exceeded");
}
I modified the mint() function instead by just adding the second line of code:
require(ERC20.totalSupply() + amount <= cap(), "ERC20Capped: cap exceeded");
As far as I can tell by testing the code it works. Did I miss something, or is my version also acceptable?
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "../node_modules/@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import "../node_modules/@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol";
import "../node_modules/@openzeppelin/contracts/access/AccessControlEnumerable.sol";
import "../node_modules/@openzeppelin/contracts/utils/Context.sol";
contract MyToken is Context, AccessControlEnumerable, ERC20Burnable, ERC20Pausable {
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
bytes32 public constant CAPPER_ROLE = keccak256("CAPPER_ROLE");
uint256 private _cap;
constructor() ERC20("MyToken", "MTKN") {
_setupRole(DEFAULT_ADMIN_ROLE, _msgSender());
_setupRole(MINTER_ROLE, _msgSender());
_setupRole(PAUSER_ROLE, _msgSender());
_setupRole(CAPPER_ROLE, _msgSender());
_cap = 100000;
}
function cap() public view virtual returns (uint256) {
return _cap;
}
function changeCap(uint256 cap_) public {
require(hasRole(CAPPER_ROLE, _msgSender()), "Must have capper role to change cap");
require(cap_ > 0, "ERC20Capped: cap is 0");
_cap = cap_;
}
function mint(address to, uint256 amount) public virtual {
require(hasRole(MINTER_ROLE, _msgSender()), "ERC20PresetMinterPauser: must have minter role to mint");
require(ERC20.totalSupply() + amount <= cap(), "ERC20Capped: cap exceeded");
_mint(to, amount);
}
function pause() public virtual {
require(hasRole(PAUSER_ROLE, _msgSender()), "ERC20PresetMinterPauser: must have pauser role to pause");
_pause();
}
function unpause() public virtual {
require(hasRole(PAUSER_ROLE, _msgSender()), "ERC20PresetMinterPauser: must have pauser role to unpause");
_unpause();
}
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override(ERC20, ERC20Pausable) {
super._beforeTokenTransfer(from, to, amount);
}
}