@@ -36,6 +36,15 @@ interface IHats {
3636contract CookieJar is AccessControl , Pausable {
3737 using SafeERC20 for IERC20 ;
3838
39+
40+ /// @notice Modifier to check if user is not denylisted
41+ modifier notDenylisted () {
42+ if (hasRole (CookieJarLib.JAR_DENYLISTED, msg .sender )) {
43+ revert CookieJarLib.UserDenylisted ();
44+ }
45+ _;
46+ }
47+
3948 /// @notice Array of approved NFT gates (used in NFTGated mode).
4049 CookieJarLib.NFTGate[] public nftGates;
4150
@@ -159,6 +168,7 @@ contract CookieJar is AccessControl, Pausable {
159168 maxWithdrawalPerPeriod = config.maxWithdrawalPerPeriod;
160169
161170 _setRoleAdmin (CookieJarLib.JAR_ALLOWLISTED, CookieJarLib.JAR_OWNER);
171+ _setRoleAdmin (CookieJarLib.JAR_DENYLISTED, CookieJarLib.JAR_OWNER);
162172 _grantRole (CookieJarLib.JAR_OWNER, config.jarOwner);
163173 _grantRoles (CookieJarLib.JAR_ALLOWLISTED, accessConfig.allowlist);
164174 }
@@ -196,6 +206,18 @@ contract CookieJar is AccessControl, Pausable {
196206 _revokeRoles (CookieJarLib.JAR_ALLOWLISTED, _users);
197207 }
198208
209+ /// @notice Grant denylist role to users to prevent them from withdrawing
210+ /// @param _users Array of addresses to add to denylist
211+ function grantJarDenylistRole (address [] calldata _users ) external onlyRole (CookieJarLib.JAR_OWNER) {
212+ _grantRoles (CookieJarLib.JAR_DENYLISTED, _users);
213+ }
214+
215+ /// @notice Revoke denylist role from users to allow them to withdraw again
216+ /// @param _users Array of addresses to remove from denylist
217+ function revokeJarDenylistRole (address [] calldata _users ) external onlyRole (CookieJarLib.JAR_OWNER) {
218+ _revokeRoles (CookieJarLib.JAR_DENYLISTED, _users);
219+ }
220+
199221 /// @notice Updates the fee collector address. Only the fee collector can call this function.
200222 /// @param _newFeeCollector The new fee collector address.
201223 function updateFeeCollector (address _newFeeCollector ) external {
@@ -488,7 +510,7 @@ contract CookieJar is AccessControl, Pausable {
488510 function withdrawAllowlistMode (
489511 uint256 amount ,
490512 string calldata purpose
491- ) external onlyRole (CookieJarLib.JAR_ALLOWLISTED) whenNotPaused {
513+ ) external onlyRole (CookieJarLib.JAR_ALLOWLISTED) whenNotPaused notDenylisted {
492514 if (accessType != CookieJarLib.AccessType.Allowlist) revert CookieJarLib.InvalidAccessType ();
493515 _checkAndUpdateWithdraw (amount, purpose, lastWithdrawalAllowlist[msg .sender ]);
494516 lastWithdrawalAllowlist[msg .sender ] = block .timestamp ;
@@ -500,7 +522,12 @@ contract CookieJar is AccessControl, Pausable {
500522 /// @param purpose A description for the withdrawal.
501523 /// @param gateAddress The NFT contract address used for gating.
502524 /// @param tokenId The NFT token id used for gating.
503- function withdrawNFTMode (uint256 amount , string calldata purpose , address gateAddress , uint256 tokenId ) external whenNotPaused {
525+ function withdrawNFTMode (
526+ uint256 amount ,
527+ string calldata purpose ,
528+ address gateAddress ,
529+ uint256 tokenId
530+ ) external whenNotPaused notDenylisted {
504531 if (accessType != CookieJarLib.AccessType.NFTGated) revert CookieJarLib.InvalidAccessType ();
505532 if (gateAddress == address (0 )) revert CookieJarLib.InvalidNFTGate ();
506533 _checkAccessNFT (gateAddress, tokenId);
@@ -576,7 +603,11 @@ contract CookieJar is AccessControl, Pausable {
576603 /// @param amount The amount to withdraw.
577604 /// @param purpose A description for the withdrawal.
578605 /// @param tokenId The POAP token ID to use for access.
579- function withdrawPOAPMode (uint256 amount , string calldata purpose , uint256 tokenId ) external whenNotPaused {
606+ function withdrawPOAPMode (
607+ uint256 amount ,
608+ string calldata purpose ,
609+ uint256 tokenId
610+ ) external whenNotPaused notDenylisted {
580611 if (accessType != CookieJarLib.AccessType.POAP) revert CookieJarLib.InvalidAccessType ();
581612 _checkAccessPOAP (tokenId);
582613 _checkAndUpdateWithdraw (amount, purpose, lastWithdrawalPOAP[tokenId]);
@@ -587,7 +618,7 @@ contract CookieJar is AccessControl, Pausable {
587618 /// @notice Withdraws funds (ETH or ERC20) for Unlock Protocol key holders.
588619 /// @param amount The amount to withdraw.
589620 /// @param purpose A description for the withdrawal.
590- function withdrawUnlockMode (uint256 amount , string calldata purpose ) external whenNotPaused {
621+ function withdrawUnlockMode (uint256 amount , string calldata purpose ) external whenNotPaused notDenylisted {
591622 if (accessType != CookieJarLib.AccessType.Unlock) revert CookieJarLib.InvalidAccessType ();
592623 _checkAccessUnlock ();
593624 _checkAndUpdateWithdraw (amount, purpose, lastWithdrawalProtocol[msg .sender ]);
@@ -599,7 +630,11 @@ contract CookieJar is AccessControl, Pausable {
599630 /// @param amount The amount to withdraw.
600631 /// @param purpose A description for the withdrawal.
601632 /// @param tokenId The hypercert token ID to use for access.
602- function withdrawHypercertMode (uint256 amount , string calldata purpose , uint256 tokenId ) external whenNotPaused {
633+ function withdrawHypercertMode (
634+ uint256 amount ,
635+ string calldata purpose ,
636+ uint256 tokenId
637+ ) external whenNotPaused notDenylisted {
603638 if (accessType != CookieJarLib.AccessType.Hypercert) revert CookieJarLib.InvalidAccessType ();
604639 _checkAccessHypercert (tokenId);
605640 _checkAndUpdateWithdraw (amount, purpose, lastWithdrawalProtocol[msg .sender ]);
@@ -610,7 +645,7 @@ contract CookieJar is AccessControl, Pausable {
610645 /// @notice Withdraws funds (ETH or ERC20) for Hats Protocol hat wearers.
611646 /// @param amount The amount to withdraw.
612647 /// @param purpose A description for the withdrawal.
613- function withdrawHatsMode (uint256 amount , string calldata purpose ) external whenNotPaused {
648+ function withdrawHatsMode (uint256 amount , string calldata purpose ) external whenNotPaused notDenylisted {
614649 if (accessType != CookieJarLib.AccessType.Hats) revert CookieJarLib.InvalidAccessType ();
615650 _checkAccessHats ();
616651 _checkAndUpdateWithdraw (amount, purpose, lastWithdrawalProtocol[msg .sender ]);
@@ -783,7 +818,7 @@ contract CookieJar is AccessControl, Pausable {
783818
784819 function _checkAccessHypercert (uint256 tokenId ) internal view {
785820 if (tokenId != hypercertRequirement.tokenId) {
786- revert CookieJarLib.InvalidAccessType ();
821+ revert CookieJarLib.NotAuthorized ();
787822 }
788823
789824 address tokenContract = hypercertRequirement.tokenContract;
0 commit comments