Skip to content

Commit 0491097

Browse files
committed
fix: misinterpretation of requirement, now each poaps give access to tickets
1 parent 41f4e4c commit 0491097

File tree

2 files changed

+103
-132
lines changed

2 files changed

+103
-132
lines changed

contracts/POAPVerifier.sol

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,65 +4,68 @@ pragma solidity 0.8.28;
44
import "@openzeppelin/contracts/access/Ownable.sol";
55

66
interface IPOAP {
7-
function balanceOf(address account, uint256 id) external view returns (uint256);
7+
function balanceOf(
8+
address account,
9+
uint256 id
10+
) external view returns (uint256);
811
}
912

1013
contract POAPVerifier is Ownable {
1114
address public poapContract;
1215
uint256[] public requiredPoapIds;
1316

14-
mapping(address => bool) public verifiedUsers;
17+
mapping(address => uint256) public userTickets; // Maps users to their ticket count
1518
address[] public verifiedUserList;
1619

17-
event UserVerified(address indexed user);
20+
event UserVerified(address indexed user, uint256 ticketCount);
1821
event PoapIdsUpdated(uint256[] newPoapIds);
1922

20-
constructor(uint256[] memory _initialPoapIds, address _poapContract) Ownable(msg.sender) {
23+
constructor(
24+
uint256[] memory _requiredPoapIds,
25+
address _poapContract
26+
) Ownable(msg.sender) {
2127
poapContract = _poapContract;
22-
requiredPoapIds = _initialPoapIds;
28+
requiredPoapIds = _requiredPoapIds;
2329
}
2430

2531
/**
26-
* @dev Updates the list of required POAP IDs. Can only be called by the owner.
27-
* @param _newPoapIds The new array of required POAP IDs.
28-
*/
29-
function updatePoapIds(uint256[] memory _newPoapIds) public onlyOwner {
30-
requiredPoapIds = _newPoapIds;
31-
emit PoapIdsUpdated(_newPoapIds);
32-
}
33-
34-
/**
35-
* @dev Checks if a user holds all required POAPs and registers them if eligible.
32+
* @dev Checks how many POAPs a user has and updates their ticket count.
3633
* @param _user The address of the user to verify.
3734
*/
3835
function checkAndRegister(address _user) public {
39-
require(!verifiedUsers[_user], "User already verified");
40-
require(checkEligibility(_user), "User does not have all required POAPs");
36+
require(
37+
userTickets[_user] < requiredPoapIds.length,
38+
"Already have all tickets"
39+
);
40+
uint256 ticketCount = calculateTickets(_user);
41+
require(ticketCount > 0, "Has no eligible POAPs");
4142

42-
verifiedUsers[_user] = true;
43+
userTickets[_user] = ticketCount;
4344
verifiedUserList.push(_user);
44-
emit UserVerified(_user);
45+
emit UserVerified(_user, ticketCount);
4546
}
4647

4748
/**
48-
* @dev Checks if a user meets the POAP requirements without registering them.
49+
* @dev Calculates the number of raffle tickets a user has based on POAP ownership.
4950
* @param _user The address of the user to check.
50-
* @return true if the user has all required POAPs, false otherwise.
51+
* @return The number of raffle tickets the user has.
5152
*/
52-
function checkEligibility(address _user) public view returns (bool) {
53+
function calculateTickets(address _user) public view returns (uint256) {
5354
IPOAP poap = IPOAP(poapContract);
55+
uint256 ticketCount = 0;
5456
for (uint256 i = 0; i < requiredPoapIds.length; i++) {
55-
if (poap.balanceOf(_user, requiredPoapIds[i]) == 0) {
56-
return false;
57+
if (poap.balanceOf(_user, requiredPoapIds[i]) > 0) {
58+
ticketCount++;
5759
}
5860
}
59-
return true;
61+
return ticketCount;
6062
}
6163

6264
/**
6365
* @dev Returns the list of verified users.
66+
* @return verifiedUserList public variable.
6467
*/
6568
function getVerifiedUsers() public view returns (address[] memory) {
6669
return verifiedUserList;
6770
}
68-
}
71+
}

test/POAPVerifierTest.t.sol

Lines changed: 74 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -2,132 +2,100 @@
22
pragma solidity 0.8.28;
33

44
import "forge-std/Test.sol";
5-
import "../contracts/MockPOAP.sol";
65
import "../contracts/POAPVerifier.sol";
6+
import "../contracts/MockPOAP.sol";
77

88
contract POAPVerifierTest is Test {
9-
MockPOAP mockPoap;
109
POAPVerifier poapVerifier;
11-
address owner = address(this);
12-
address addr1 = address(0x1);
13-
address addr2 = address(0x2);
14-
address addr3 = address(0x3);
15-
address addr4 = address(0x4);
10+
MockPOAP mockPOAP;
11+
address owner;
12+
address user1;
13+
address user2;
1614

1715
function setUp() public {
18-
// Deploy a mock POAP contract
19-
mockPoap = new MockPOAP();
20-
21-
// Declare a dynamic uint256 array in memory
22-
uint256[] memory poapIds = new uint256[](4);
23-
poapIds[0] = 1;
24-
poapIds[1] = 2;
25-
poapIds[2] = 3;
26-
poapIds[3] = 4;
27-
28-
// Deploy the POAPVerifier contract with the correctly formatted array
29-
poapVerifier = new POAPVerifier(poapIds, address(mockPoap));
16+
// Deploy the MockPOAP contract
17+
mockPOAP = new MockPOAP();
18+
owner = address(this); // The test contract is the owner of MockPOAP
19+
20+
// Initialize the POAPVerifier contract with required POAP IDs and the MockPOAP address
21+
uint256[] memory requiredPoapIds = new uint256[](3);
22+
requiredPoapIds[0] = 1;
23+
requiredPoapIds[1] = 2;
24+
requiredPoapIds[2] = 3;
25+
26+
poapVerifier = new POAPVerifier(requiredPoapIds, address(mockPOAP));
27+
28+
// Create some test users
29+
user1 = address(0x1);
30+
user2 = address(0x2);
3031
}
3132

32-
function testMintPoaps() public {
33-
// Mint POAPs to different addresses and verify balances
33+
function testUserVerification() public {
34+
// Mint POAPs for user1
35+
mockPOAP.mint(user1, 1); // user1 gets POAP ID 1
36+
mockPOAP.mint(user1, 2); // user1 gets POAP ID 2
3437

35-
// Address 1 receives 1 type of POAP
36-
mockPoap.mint(addr1, 1);
37-
assertEq(mockPoap.balanceOf(addr1, 1), 1);
38+
// Verify user1
39+
poapVerifier.checkAndRegister(user1);
3840

39-
// Address 2 receives 2 types of POAPs
40-
mockPoap.mint(addr2, 1);
41-
mockPoap.mint(addr2, 2);
42-
assertEq(mockPoap.balanceOf(addr2, 1), 1);
43-
assertEq(mockPoap.balanceOf(addr2, 2), 1);
41+
// Check that user1 has 2 tickets
42+
uint256 ticketCount = poapVerifier.calculateTickets(user1);
43+
assertEq(ticketCount, 2);
4444

45-
// Address 3 receives 2 types of POAPs, 2 of each
46-
uint256[] memory ids = new uint256[](2);
47-
ids[0] = 2;
48-
ids[1] = 3;
49-
uint256[] memory amounts = new uint256[](2);
50-
amounts[0] = 2;
51-
amounts[1] = 2;
52-
mockPoap.mintBatch(addr3, ids, amounts, "");
53-
54-
assertEq(mockPoap.balanceOf(addr3, 2), 2);
55-
assertEq(mockPoap.balanceOf(addr3, 3), 2);
56-
57-
// Address 4 receives 4 different POAPs
58-
uint256[] memory allIds = new uint256[](4);
59-
allIds[0] = 1;
60-
allIds[1] = 2;
61-
allIds[2] = 3;
62-
allIds[3] = 4;
63-
uint256[] memory allAmounts = new uint256[](4);
64-
allAmounts[0] = 1;
65-
allAmounts[1] = 1;
66-
allAmounts[2] = 1;
67-
allAmounts[3] = 1;
68-
mockPoap.mintBatch(addr4, allIds, allAmounts, "");
69-
70-
assertEq(mockPoap.balanceOf(addr4, 1), 1);
71-
assertEq(mockPoap.balanceOf(addr4, 2), 1);
72-
assertEq(mockPoap.balanceOf(addr4, 3), 1);
73-
assertEq(mockPoap.balanceOf(addr4, 4), 1);
45+
// Check that user1 is in the verified user list
46+
address[] memory verifiedUsers = poapVerifier.getVerifiedUsers();
47+
assertEq(verifiedUsers.length, 1);
48+
assertEq(verifiedUsers[0], user1);
7449
}
7550

76-
function testVerifyUsers() public {
77-
// Mint all required POAPs to addr4 to make them eligible
78-
uint256[] memory ids = new uint256[](4);
79-
ids[0] = 1;
80-
ids[1] = 2;
81-
ids[2] = 3;
82-
ids[3] = 4;
83-
uint256[] memory amounts = new uint256[](4);
84-
amounts[0] = 1;
85-
amounts[1] = 1;
86-
amounts[2] = 1;
87-
amounts[3] = 1;
88-
mockPoap.mintBatch(addr4, ids, amounts, "");
51+
function testUserCannotGetMoreTicketsThanAvailable() public {
52+
// Mint all required POAPs for user2
53+
mockPOAP.mint(user2, 1); // user2 gets POAP ID 1
54+
mockPOAP.mint(user2, 2); // user2 gets POAP ID 2
55+
mockPOAP.mint(user2, 3); // user2 gets POAP ID 3
8956

90-
// The user should pass the verification
91-
poapVerifier.checkAndRegister(addr4);
92-
assertTrue(poapVerifier.verifiedUsers(addr4));
57+
// Verify user2
58+
poapVerifier.checkAndRegister(user2);
9359

94-
// Address 1 does not have all required POAPs, should revert
95-
vm.expectRevert("User does not have all required POAPs");
96-
poapVerifier.checkAndRegister(addr1);
60+
// Check that user2 has 3 tickets
61+
uint256 ticketCount = poapVerifier.calculateTickets(user2);
62+
assertEq(ticketCount, 3);
63+
64+
// Try to verify user2 again, should fail
65+
vm.expectRevert("Already have all tickets");
66+
poapVerifier.checkAndRegister(user2);
67+
}
68+
69+
function testUserWithNoEligiblePOAPs() public {
70+
// Do not mint any POAPs for user1
71+
72+
// Try to verify user1, should fail
73+
vm.expectRevert("Has no eligible POAPs");
74+
poapVerifier.checkAndRegister(user1);
9775
}
9876

99-
function testCannotRegisterTwice() public {
100-
// Mint all required POAPs to addr4
101-
uint256[] memory ids = new uint256[](4);
102-
ids[0] = 1;
103-
ids[1] = 2;
104-
ids[2] = 3;
105-
ids[3] = 4;
106-
uint256[] memory amounts = new uint256[](4);
77+
function testBatchMintingAndVerification() public {
78+
// Mint multiple POAPs in a batch for user1
79+
uint256[] memory tokenIds = new uint256[](2);
80+
tokenIds[0] = 1;
81+
tokenIds[1] = 2;
82+
83+
uint256[] memory amounts = new uint256[](2);
10784
amounts[0] = 1;
10885
amounts[1] = 1;
109-
amounts[2] = 1;
110-
amounts[3] = 1;
111-
mockPoap.mintBatch(addr4, ids, amounts, "");
11286

113-
// First registration should succeed
114-
poapVerifier.checkAndRegister(addr4);
87+
mockPOAP.mintBatch(user1, tokenIds, amounts, "");
11588

116-
// Second registration should revert
117-
vm.expectRevert("User already verified");
118-
poapVerifier.checkAndRegister(addr4);
119-
}
89+
// Verify user1
90+
poapVerifier.checkAndRegister(user1);
91+
92+
// Check that user1 has 2 tickets
93+
uint256 ticketCount = poapVerifier.calculateTickets(user1);
94+
assertEq(ticketCount, 2);
12095

121-
function testOnlyOwnerCanUpdatePoaps() public {
122-
// Only the owner should be able to update the required POAP IDs
123-
uint256[] memory newPoaps = new uint256[](2);
124-
newPoaps[0] = 1;
125-
newPoaps[1] = 3;
126-
poapVerifier.updatePoapIds(newPoaps);
127-
128-
// A non-owner should not be able to update POAP IDs
129-
vm.prank(addr1);
130-
vm.expectRevert();
131-
poapVerifier.updatePoapIds(newPoaps);
96+
// Check that user1 is in the verified user list
97+
address[] memory verifiedUsers = poapVerifier.getVerifiedUsers();
98+
assertEq(verifiedUsers.length, 1);
99+
assertEq(verifiedUsers[0], user1);
132100
}
133-
}
101+
}

0 commit comments

Comments
 (0)