-
Notifications
You must be signed in to change notification settings - Fork 0
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
feat: capped minter v2 close #12
Changes from 31 commits
9f8ea6e
2aecdce
e293e2d
b7f4222
726d0bf
31d626f
fb88648
946dc79
d9b3dba
1cfbef7
3379852
004c789
4f29f5c
edf05f6
bceb0f7
e680c31
6ee3fb1
72ef93c
dd15cac
61e7247
1295f88
54315f5
2558249
857ebc6
479ef77
007784b
bfbac0e
8a5f057
493c1a6
7d84ebe
6bb7d1a
fca3ffb
93e4af3
225ba92
1942a64
77acf62
ecb275d
43fa666
7da3772
57e1f4f
ef8ca96
3fc7d3a
bb6854b
0b17e88
7631a29
246efdc
91c0ca8
aa47d27
48c9ca6
fe1cac7
c7bef58
010e4c5
960a751
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
[profile.default] | ||
evm_version = "paris" | ||
fs_permissions = [{ access = "read", path = "./zkout" }] | ||
fuzz = { runs = 50 } | ||
optimizer = true | ||
optimizer_runs = 10_000_000 | ||
|
@@ -8,10 +9,10 @@ | |
"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", | ||
"@openzeppelin/foundry-upgrades/=lib/openzeppelin-foundry-upgrades/src/", | ||
"@murky/=lib/murky/", | ||
"src/=src/", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This can be removed There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
] | ||
solc_version = "0.8.24" | ||
verbosity = 3 | ||
fs_permissions = [{ access = "read", path = "./zkout" }] | ||
|
||
[profile.ci] | ||
fuzz = { runs = 5000 } | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,63 +1,94 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity 0.8.24; | ||
|
||
import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"; | ||
import {Pausable} from "@openzeppelin/contracts/security/Pausable.sol"; | ||
import {IMintableAndDelegatable} from "src/interfaces/IMintableAndDelegatable.sol"; | ||
|
||
/// @title ZkCappedMinterV2 | ||
/// @author [ScopeLift](https://scopelift.co) | ||
/// @notice A contract to allow a permissioned entity to mint ZK tokens up to a given amount (the cap). | ||
/// @custom:security-contact [email protected] | ||
contract ZkCappedMinterV2 { | ||
contract ZkCappedMinterV2 is AccessControl, Pausable { | ||
/// @notice The contract where the tokens will be minted by an authorized minter. | ||
IMintableAndDelegatable public immutable TOKEN; | ||
|
||
/// @notice The address that is allowed to mint tokens. | ||
address public immutable ADMIN; | ||
|
||
/// @notice The maximum number of tokens that may be minted by the ZkCappedMinter. | ||
uint256 public immutable CAP; | ||
|
||
/// @notice The cumulative number of tokens that have been minted by the ZkCappedMinter. | ||
uint256 public minted = 0; | ||
|
||
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); | ||
bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); | ||
|
||
/// @notice Whether the contract has been permanently closed. | ||
bool public closed; | ||
|
||
/// @notice Error for when the cap is exceeded. | ||
error ZkCappedMinterV2__CapExceeded(address minter, uint256 amount); | ||
|
||
/// @notice Error for when the caller is not the admin. | ||
error ZkCappedMinterV2__Unauthorized(address account); | ||
/// @notice Error for when the contract is closed. | ||
marcomariscal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
error ZkCappedMinterV2__ContractClosed(); | ||
|
||
/// @notice Constructor for a new ZkCappedMinter contract | ||
/// @notice Constructor for a new ZkCappedMinterV2 contract | ||
/// @param _token The token contract where tokens will be minted. | ||
/// @param _admin The address that is allowed to mint tokens. | ||
/// @param _admin The address that will be granted the admin role. | ||
/// @param _cap The maximum number of tokens that may be minted by the ZkCappedMinter. | ||
constructor(IMintableAndDelegatable _token, address _admin, uint256 _cap) { | ||
TOKEN = _token; | ||
ADMIN = _admin; | ||
CAP = _cap; | ||
|
||
_grantRole(DEFAULT_ADMIN_ROLE, _admin); | ||
_grantRole(PAUSER_ROLE, _admin); | ||
} | ||
|
||
/// @notice Pauses token minting | ||
function pause() external { | ||
_checkRole(PAUSER_ROLE, msg.sender); | ||
_pause(); | ||
} | ||
|
||
/// @notice Unpauses token minting | ||
function unpause() external { | ||
_revertIfClosed(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It don't think we need to revert here, since unpausing will have no effect right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yee you're right: |
||
_checkRole(PAUSER_ROLE, msg.sender); | ||
_unpause(); | ||
} | ||
|
||
/// @notice Mints a given amount of tokens to a given address, so long as the cap is not exceeded. | ||
/// @param _to The address that will receive the new tokens. | ||
/// @param _amount The quantity of tokens, in raw decimals, that will be created. | ||
function mint(address _to, uint256 _amount) external { | ||
_revertIfUnauthorized(); | ||
_revertIfClosed(); | ||
_requireNotPaused(); | ||
_checkRole(MINTER_ROLE, msg.sender); | ||
_revertIfCapExceeded(_amount); | ||
minted += _amount; | ||
TOKEN.mint(_to, _amount); | ||
} | ||
|
||
/// @notice Reverts if msg.sender is not the contract admin. | ||
function _revertIfUnauthorized() internal view { | ||
if (msg.sender != ADMIN) { | ||
revert ZkCappedMinterV2__Unauthorized(msg.sender); | ||
} | ||
} | ||
|
||
/// @notice Reverts if the amount of new tokens will increase the minted tokens beyond the mint cap. | ||
/// @param _amount The quantity of tokens, in raw decimals, that will checked against the cap. | ||
function _revertIfCapExceeded(uint256 _amount) internal view { | ||
if (minted + _amount > CAP) { | ||
revert ZkCappedMinterV2__CapExceeded(msg.sender, _amount); | ||
} | ||
} | ||
|
||
/// @notice Reverts if the contract is closed. | ||
function _revertIfClosed() internal view { | ||
if (closed) { | ||
revert ZkCappedMinterV2__ContractClosed(); | ||
} | ||
} | ||
|
||
/// @notice Permanently closes the contract, preventing any future minting. | ||
/// @dev Once closed, the contract cannot be reopened and all minting operations will be permanently blocked. | ||
/// @dev Only callable by accounts with the PAUSER_ROLE. | ||
function close() external { | ||
_checkRole(PAUSER_ROLE, msg.sender); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we only want the admin to be able to close There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
closed = true; | ||
_pause(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why pause here as well? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ah yep unnecessary: |
||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
91c0ca8