@@ -6,7 +6,54 @@ import "contracts/drop/DropERC721.sol";
66// Test imports
77import "../utils/BaseTest.sol " ;
88
9- contract BaseDropERC721Test is BaseTest {
9+ contract SubExploitContract is ERC721Holder , ERC1155Holder {
10+ DropERC721 internal drop;
11+ address payable internal master;
12+
13+ constructor (address _drop ) {
14+ drop = DropERC721 (_drop);
15+ master = payable (msg .sender );
16+ }
17+
18+ /// @dev Lets an account claim NFTs.
19+ function claimDrop (
20+ address _receiver ,
21+ uint256 _quantity ,
22+ address _currency ,
23+ uint256 _pricePerToken ,
24+ bytes32 [] calldata _proofs ,
25+ uint256 _proofMaxQuantityPerTransaction
26+ ) external {
27+ drop.claim (_receiver, _quantity, _currency, _pricePerToken, _proofs, _proofMaxQuantityPerTransaction);
28+
29+ selfdestruct (master);
30+ }
31+ }
32+
33+ contract MasterExploitContract is ERC721Holder , ERC1155Holder {
34+ address internal drop;
35+
36+ constructor (address _drop ) {
37+ drop = _drop;
38+ }
39+
40+ /// @dev Lets an account claim NFTs.
41+ function performExploit (
42+ address _receiver ,
43+ uint256 _quantity ,
44+ address _currency ,
45+ uint256 _pricePerToken ,
46+ bytes32 [] calldata _proofs ,
47+ uint256 _proofMaxQuantityPerTransaction
48+ ) external {
49+ for (uint256 i = 0 ; i < 100 ; i++ ) {
50+ SubExploitContract sub = new SubExploitContract (address (drop));
51+ sub.claimDrop (_receiver, _quantity, _currency, _pricePerToken, _proofs, _proofMaxQuantityPerTransaction);
52+ }
53+ }
54+ }
55+
56+ contract DropERC721Test is BaseTest {
1057 DropERC721 public drop;
1158
1259 function setUp () public override {
@@ -99,7 +146,6 @@ contract BaseDropERC721Test is BaseTest {
99146 }
100147
101148 function test_claimCondition_waitTimeInSecondsBetweenClaims () public {
102- vm.startPrank (deployer);
103149 vm.warp (1 );
104150
105151 address receiver = getActor (0 );
@@ -110,16 +156,20 @@ contract BaseDropERC721Test is BaseTest {
110156 conditions[0 ].quantityLimitPerTransaction = 100 ;
111157 conditions[0 ].waitTimeInSecondsBetweenClaims = type (uint256 ).max;
112158
159+ vm.prank (deployer);
113160 drop.lazyMint (100 , "ipfs:// " , bytes ("" ));
161+ vm.prank (deployer);
114162 drop.setClaimConditions (conditions, false );
163+
164+ vm.prank (getActor (5 ), getActor (5 ));
115165 drop.claim (receiver, 1 , address (0 ), 0 , proofs, 0 );
116166
117167 vm.expectRevert ("cannot claim. " );
168+ vm.prank (getActor (5 ), getActor (5 ));
118169 drop.claim (receiver, 1 , address (0 ), 0 , proofs, 0 );
119170 }
120171
121172 function test_claimCondition_resetEligibility_waitTimeInSecondsBetweenClaims () public {
122- vm.startPrank (deployer);
123173 vm.warp (1 );
124174
125175 address receiver = getActor (0 );
@@ -130,12 +180,47 @@ contract BaseDropERC721Test is BaseTest {
130180 conditions[0 ].quantityLimitPerTransaction = 100 ;
131181 conditions[0 ].waitTimeInSecondsBetweenClaims = type (uint256 ).max;
132182
183+ vm.prank (deployer);
133184 drop.lazyMint (100 , "ipfs:// " , bytes ("" ));
134185
186+ vm.prank (deployer);
135187 drop.setClaimConditions (conditions, false );
188+
189+ vm.prank (getActor (5 ), getActor (5 ));
136190 drop.claim (receiver, 1 , address (0 ), 0 , proofs, 0 );
137191
192+ vm.prank (deployer);
138193 drop.setClaimConditions (conditions, true );
194+
195+ vm.prank (getActor (5 ), getActor (5 ));
139196 drop.claim (receiver, 1 , address (0 ), 0 , proofs, 0 );
140197 }
198+
199+ function test_multiple_claim_exploit () public {
200+ MasterExploitContract masterExploit = new MasterExploitContract (address (drop));
201+
202+ DropERC721.ClaimCondition[] memory conditions = new DropERC721.ClaimCondition [](1 );
203+ conditions[0 ].maxClaimableSupply = 100 ;
204+ conditions[0 ].quantityLimitPerTransaction = 1 ;
205+ conditions[0 ].waitTimeInSecondsBetweenClaims = type (uint256 ).max;
206+
207+ vm.prank (deployer);
208+ drop.lazyMint (100 , "ipfs:// " , bytes ("" ));
209+
210+ vm.prank (deployer);
211+ drop.setClaimConditions (conditions, false );
212+
213+ bytes32 [] memory proofs = new bytes32 [](0 );
214+
215+ vm.startPrank (getActor (5 ));
216+ vm.expectRevert (bytes ("BOT " ));
217+ masterExploit.performExploit (
218+ address (masterExploit),
219+ conditions[0 ].quantityLimitPerTransaction,
220+ conditions[0 ].currency,
221+ conditions[0 ].pricePerToken,
222+ proofs,
223+ 0
224+ );
225+ }
141226}
0 commit comments