Skip to content

Commit 3c254ac

Browse files
committed
Merge branch 'dev' of github.com:greenpill-dev-guild/cookie-jar into enhancement/e2e-test-infra
2 parents 5a4f9c5 + 5934878 commit 3c254ac

File tree

6 files changed

+103
-14
lines changed

6 files changed

+103
-14
lines changed

client/generated.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,13 @@ export const cookieJarAbi = [
301301
outputs: [],
302302
stateMutability: 'nonpayable',
303303
},
304+
{
305+
type: 'function',
306+
inputs: [{ name: '_users', internalType: 'address[]', type: 'address[]' }],
307+
name: 'grantJarDenylistRole',
308+
outputs: [],
309+
stateMutability: 'nonpayable',
310+
},
304311
{
305312
type: 'function',
306313
inputs: [
@@ -487,6 +494,13 @@ export const cookieJarAbi = [
487494
outputs: [],
488495
stateMutability: 'nonpayable',
489496
},
497+
{
498+
type: 'function',
499+
inputs: [{ name: '_users', internalType: 'address[]', type: 'address[]' }],
500+
name: 'revokeJarDenylistRole',
501+
outputs: [],
502+
stateMutability: 'nonpayable',
503+
},
490504
{
491505
type: 'function',
492506
inputs: [
@@ -1054,6 +1068,7 @@ export const cookieJarAbi = [
10541068
},
10551069
{ type: 'error', inputs: [], name: 'TooManyNFTGates' },
10561070
{ type: 'error', inputs: [], name: 'TransferFailed' },
1071+
{ type: 'error', inputs: [], name: 'UserDenylisted' },
10571072
{ type: 'error', inputs: [], name: 'WithdrawalAlreadyDone' },
10581073
{
10591074
type: 'error',
@@ -2029,6 +2044,15 @@ export const useWriteCookieJarGrantJarAllowlistRole =
20292044
functionName: 'grantJarAllowlistRole',
20302045
})
20312046

2047+
/**
2048+
* Wraps __{@link useWriteContract}__ with `abi` set to __{@link cookieJarAbi}__ and `functionName` set to `"grantJarDenylistRole"`
2049+
*/
2050+
export const useWriteCookieJarGrantJarDenylistRole =
2051+
/*#__PURE__*/ createUseWriteContract({
2052+
abi: cookieJarAbi,
2053+
functionName: 'grantJarDenylistRole',
2054+
})
2055+
20322056
/**
20332057
* Wraps __{@link useWriteContract}__ with `abi` set to __{@link cookieJarAbi}__ and `functionName` set to `"grantRole"`
20342058
*/
@@ -2072,6 +2096,15 @@ export const useWriteCookieJarRevokeJarAllowlistRole =
20722096
functionName: 'revokeJarAllowlistRole',
20732097
})
20742098

2099+
/**
2100+
* Wraps __{@link useWriteContract}__ with `abi` set to __{@link cookieJarAbi}__ and `functionName` set to `"revokeJarDenylistRole"`
2101+
*/
2102+
export const useWriteCookieJarRevokeJarDenylistRole =
2103+
/*#__PURE__*/ createUseWriteContract({
2104+
abi: cookieJarAbi,
2105+
functionName: 'revokeJarDenylistRole',
2106+
})
2107+
20752108
/**
20762109
* Wraps __{@link useWriteContract}__ with `abi` set to __{@link cookieJarAbi}__ and `functionName` set to `"revokeRole"`
20772110
*/
@@ -2238,6 +2271,15 @@ export const useSimulateCookieJarGrantJarAllowlistRole =
22382271
functionName: 'grantJarAllowlistRole',
22392272
})
22402273

2274+
/**
2275+
* Wraps __{@link useSimulateContract}__ with `abi` set to __{@link cookieJarAbi}__ and `functionName` set to `"grantJarDenylistRole"`
2276+
*/
2277+
export const useSimulateCookieJarGrantJarDenylistRole =
2278+
/*#__PURE__*/ createUseSimulateContract({
2279+
abi: cookieJarAbi,
2280+
functionName: 'grantJarDenylistRole',
2281+
})
2282+
22412283
/**
22422284
* Wraps __{@link useSimulateContract}__ with `abi` set to __{@link cookieJarAbi}__ and `functionName` set to `"grantRole"`
22432285
*/
@@ -2283,6 +2325,15 @@ export const useSimulateCookieJarRevokeJarAllowlistRole =
22832325
functionName: 'revokeJarAllowlistRole',
22842326
})
22852327

2328+
/**
2329+
* Wraps __{@link useSimulateContract}__ with `abi` set to __{@link cookieJarAbi}__ and `functionName` set to `"revokeJarDenylistRole"`
2330+
*/
2331+
export const useSimulateCookieJarRevokeJarDenylistRole =
2332+
/*#__PURE__*/ createUseSimulateContract({
2333+
abi: cookieJarAbi,
2334+
functionName: 'revokeJarDenylistRole',
2335+
})
2336+
22862337
/**
22872338
* Wraps __{@link useSimulateContract}__ with `abi` set to __{@link cookieJarAbi}__ and `functionName` set to `"revokeRole"`
22882339
*/

client/hooks/useCookieJar.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,14 @@ export const useCookieJarConfig = (address: `0x${string}`) => {
3232
const chainId = useChainId()
3333

3434
const JAR_OWNER = keccak256(toHex("JAR_OWNER")) as `0x${string}`
35-
const JAR_DENYLISTED = keccak256(toHex("JAR_DENYLISTED")) as `0x${string}`
3635

37-
// Use correct role name based on contract version
36+
// Use correct role names based on contract version
3837
const allowlistRoleName = isV2Chain(chainId) ? "JAR_ALLOWLISTED" : "JAR_WHITELISTED"
3938
const JAR_ALLOWLISTED = keccak256(toHex(allowlistRoleName)) as `0x${string}`
4039

40+
const denylistRoleName = isV2Chain(chainId) ? "JAR_DENYLISTED" : "JAR_BLACKLISTED"
41+
const JAR_DENYLISTED = keccak256(toHex(denylistRoleName)) as `0x${string}`
42+
4143
// Use correct function name based on contract version
4244
const lastWithdrawalFunctionName = isV2Chain(chainId) ? "lastWithdrawalAllowlist" : "lastWithdrawalWhitelist"
4345

contracts/src/CookieJar.sol

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,15 @@ interface IHats {
3636
contract 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;

contracts/src/libraries/CookieJarLib.sol

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ library CookieJarLib {
5656
// --- Constants ---
5757
bytes32 public constant JAR_OWNER = keccak256("JAR_OWNER");
5858
bytes32 public constant JAR_ALLOWLISTED = keccak256("JAR_ALLOWLISTED");
59+
bytes32 public constant JAR_DENYLISTED = keccak256("JAR_DENYLISTED");
5960

6061
// --- Structs ---
6162
/// @notice Represents an NFT gate with a contract address and its NFT type.

contracts/test/CookieJarProtocols.t.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@ contract CookieJarProtocolsTest is Test {
442442

443443
vm.warp(block.timestamp + withdrawalInterval + 1);
444444
vm.prank(user);
445-
vm.expectRevert(abi.encodeWithSelector(CookieJarLib.InvalidAccessType.selector));
445+
vm.expectRevert(abi.encodeWithSelector(CookieJarLib.NotAuthorized.selector));
446446
jarHypercert.withdrawHypercertMode(fixedAmount, purpose, testTokenId + 1);
447447
}
448448

contracts/test/NFTGatingEnhanced.t.sol

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,10 +108,10 @@ contract NFTGatingEnhancedTest is Test {
108108
nftAddresses: nftAddresses,
109109
nftTypes: nftTypes,
110110
allowlist: emptyAllowlist,
111-
poapReq: CookieJarLib.POAPRequirement(0, address(0)),
112-
unlockReq: CookieJarLib.UnlockRequirement(address(0)),
113-
hypercertReq: CookieJarLib.HypercertRequirement(address(0), 0, 1),
114-
hatsReq: CookieJarLib.HatsRequirement(0, address(0))
111+
poapReq: CookieJarLib.POAPRequirement({eventId: 0, poapContract: address(0)}),
112+
unlockReq: CookieJarLib.UnlockRequirement({lockAddress: address(0)}),
113+
hypercertReq: CookieJarLib.HypercertRequirement({tokenContract: address(0), tokenId: 0, minBalance: 0}),
114+
hatsReq: CookieJarLib.HatsRequirement({hatId: 0, hatsContract: address(0)})
115115
});
116116

117117
// Deploy the jar

0 commit comments

Comments
 (0)