@zoralabs/comments-contracts 0.0.1 → 0.0.2-COMMENTS.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +48 -30
- package/CHANGELOG.md +8 -0
- package/README.md +10 -39
- package/abis/AddDelegateCommenterRole.json +22 -0
- package/abis/CallerAndCommenter.json +62 -0
- package/abis/CallerAndCommenterImpl.json +1218 -0
- package/abis/CallerAndCommenterMintAndCommentTest.json +771 -0
- package/abis/CallerAndCommenterSwapAndCommentTest.json +844 -0
- package/abis/CallerAndCommenterTestBase.json +577 -0
- package/abis/CommentsImpl.json +189 -59
- package/abis/CommentsImplConstants.json +106 -0
- package/abis/CommentsPermitTest.json +26 -6
- package/abis/CommentsTest.json +58 -10
- package/abis/Comments_mintAndCommentTest.json +11 -4
- package/abis/Comments_smartWallet.json +711 -0
- package/abis/DeployCallerAndCommenterImpl.json +22 -0
- package/abis/EIP712Upgradeable.json +74 -0
- package/abis/EIP712UpgradeableWithChainId.json +49 -0
- package/abis/ERC20.json +310 -0
- package/abis/ICallerAndCommenter.json +797 -0
- package/abis/IComments.json +629 -9
- package/abis/IERC20.json +39 -42
- package/abis/IERC20Metadata.json +224 -0
- package/abis/IMultiOwnable.json +21 -0
- package/abis/IProtocolRewards.json +19 -0
- package/abis/ISecondarySwap.json +45 -0
- package/abis/IZoraCreator1155.json +51 -0
- package/abis/IZoraTimedSaleStrategy.json +91 -0
- package/abis/Mock1155.json +75 -1
- package/abis/Mock1155NoCreatorRewardRecipient.json +605 -0
- package/abis/Mock1155NoOwner.json +566 -0
- package/abis/{MockMinter.json → MockDelegateCommenter.json} +12 -2
- package/abis/MockERC20z.json +315 -0
- package/abis/MockMultiOwnable.json +212 -0
- package/abis/MockSecondarySwap.json +95 -0
- package/abis/MockZoraTimedSale.json +139 -0
- package/abis/Ownable2StepUpgradeable.json +138 -0
- package/abis/UnorderedNoncesUpgradeable.json +4 -4
- package/addresses/10.json +9 -0
- package/addresses/11155111.json +9 -0
- package/addresses/11155420.json +9 -0
- package/addresses/42161.json +9 -0
- package/addresses/7777777.json +9 -0
- package/addresses/8453.json +9 -0
- package/addresses/84532.json +9 -0
- package/addresses/999999999.json +7 -2
- package/deterministicConfig/callerAndCommenter.json +8 -0
- package/deterministicConfig/comments.json +2 -2
- package/dist/index.cjs +724 -35
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +723 -35
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/wagmiGenerated.d.ts +1102 -57
- package/dist/wagmiGenerated.d.ts.map +1 -1
- package/package/types.ts +4 -1
- package/package/wagmiGenerated.ts +728 -32
- package/package.json +11 -10
- package/script/AddDelegateCommenterRole.s.sol +24 -0
- package/script/CommentsDeployerBase.sol +101 -19
- package/script/Deploy.s.sol +2 -44
- package/script/DeployCallerAndCommenterImpl.s.sol +27 -0
- package/script/DeployImpl.s.sol +1 -0
- package/script/DeployNonDeterministic.s.sol +22 -13
- package/script/GenerateDeterministicParams.s.sol +32 -4
- package/scripts/generateCommentsTestData.ts +170 -79
- package/src/CommentsImpl.sol +267 -134
- package/src/CommentsImplConstants.sol +44 -0
- package/src/interfaces/ICallerAndCommenter.sol +215 -0
- package/src/interfaces/IComments.sol +189 -42
- package/src/interfaces/IMultiOwnable.sol +10 -0
- package/src/interfaces/ISecondarySwap.sol +40 -0
- package/src/interfaces/IZoraCreator1155.sol +6 -1
- package/src/interfaces/IZoraCreator1155TypesV1.sol +46 -0
- package/src/interfaces/IZoraTimedSaleStrategy.sol +25 -0
- package/src/proxy/CallerAndCommenter.sol +43 -0
- package/src/utils/CallerAndCommenterImpl.sol +376 -0
- package/src/utils/EIP712UpgradeableWithChainId.sol +12 -23
- package/src/version/ContractVersionBase.sol +1 -1
- package/test/CallerAndCommenterTestBase.sol +77 -0
- package/test/CallerAndCommenter_mintAndComment.t copy.sol +214 -0
- package/test/CallerAndCommenter_swapAndComment.t.sol +523 -0
- package/test/Comments.t.sol +166 -29
- package/test/CommentsTestBase.sol +12 -20
- package/test/Comments_delegateComment.t.sol +129 -0
- package/test/Comments_permit.t.sol +131 -44
- package/test/Comments_smartWallet.t.sol +152 -0
- package/test/mocks/Mock1155.sol +12 -1
- package/test/mocks/Mock1155NoCreatorRewardRecipient.sol +65 -0
- package/test/mocks/Mock1155NoOwner.sol +53 -0
- package/test/mocks/MockDelegateCommenter.sol +36 -0
- package/test/mocks/MockIZoraCreator1155.sol +16 -0
- package/test/mocks/MockSecondarySwap.sol +30 -0
- package/test/mocks/MockZoraTimedSale.sol +38 -0
- package/wagmi.config.ts +3 -1
- package/scripts/backfillComments.ts +0 -176
- package/scripts/queries.ts +0 -73
- package/scripts/queryAndSaveComments.ts +0 -48
- package/scripts/queryQuantityOfComments.ts +0 -53
- package/scripts/writeComments.ts +0 -198
- package/src/deployments/CommentsDeployment.sol +0 -14
- package/test/Comments_mintAndComment.t.sol +0 -101
- package/test/mocks/MockMinter.sol +0 -29
package/test/Comments.t.sol
CHANGED
|
@@ -3,21 +3,20 @@ pragma solidity ^0.8.20;
|
|
|
3
3
|
|
|
4
4
|
import "forge-std/Test.sol";
|
|
5
5
|
|
|
6
|
-
import {CommentsImpl} from "../src/CommentsImpl.sol";
|
|
7
|
-
import {Comments} from "../src/proxy/Comments.sol";
|
|
8
6
|
import {IComments} from "../src/interfaces/IComments.sol";
|
|
9
7
|
import {Mock1155} from "./mocks/Mock1155.sol";
|
|
10
|
-
import {IProtocolRewards} from "@zoralabs/protocol-rewards/src/interfaces/IProtocolRewards.sol";
|
|
11
|
-
import {ProtocolRewards} from "./mocks/ProtocolRewards.sol";
|
|
12
|
-
import {UnorderedNoncesUpgradeable} from "@zoralabs/shared-contracts/utils/UnorderedNoncesUpgradeable.sol";
|
|
13
8
|
import {CommentsTestBase} from "./CommentsTestBase.sol";
|
|
9
|
+
import {Mock1155NoCreatorRewardRecipient} from "./mocks/Mock1155NoCreatorRewardRecipient.sol";
|
|
10
|
+
import {Mock1155NoOwner} from "./mocks/Mock1155NoOwner.sol";
|
|
11
|
+
import {CommentsImpl} from "../src/CommentsImpl.sol";
|
|
12
|
+
import {Comments} from "../src/proxy/Comments.sol";
|
|
14
13
|
|
|
15
14
|
contract CommentsTest is CommentsTestBase {
|
|
16
15
|
uint256 public constant ZORA_REWARD_PCT = 10;
|
|
17
16
|
uint256 public constant REFERRER_REWARD_PCT = 20;
|
|
18
17
|
uint256 internal constant BPS_TO_PERCENT_2_DECIMAL_PERCISION = 100;
|
|
19
18
|
|
|
20
|
-
function _setupCommenterWithTokenAndSparks(address commenter,
|
|
19
|
+
function _setupCommenterWithTokenAndSparks(address commenter, uint256 sparksQuantity) internal {
|
|
21
20
|
vm.startPrank(commenter);
|
|
22
21
|
mock1155.mint(commenter, tokenId1, 1, "");
|
|
23
22
|
vm.stopPrank();
|
|
@@ -60,7 +59,7 @@ contract CommentsTest is CommentsTestBase {
|
|
|
60
59
|
address(0)
|
|
61
60
|
);
|
|
62
61
|
vm.prank(collectorWithToken);
|
|
63
|
-
comments.comment{value: SPARKS_VALUE}(collectorWithToken, contractAddress, tokenId, "test comment", replyTo, address(0));
|
|
62
|
+
comments.comment{value: SPARKS_VALUE}(collectorWithToken, contractAddress, tokenId, "test comment", replyTo, address(0), address(0));
|
|
64
63
|
|
|
65
64
|
uint256 zoraReward = (SPARKS_VALUE * (ZORA_REWARD_PCT + REFERRER_REWARD_PCT)) / BPS_TO_PERCENT_2_DECIMAL_PERCISION;
|
|
66
65
|
vm.assertEq(protocolRewards.balanceOf(collectorWithToken), 0);
|
|
@@ -102,7 +101,7 @@ contract CommentsTest is CommentsTestBase {
|
|
|
102
101
|
// verify first comment is emitted
|
|
103
102
|
emit IComments.BackfilledComment({
|
|
104
103
|
commentId: comments.hashCommentIdentifier(commentIdentifiers[0]),
|
|
105
|
-
|
|
104
|
+
commentIdentifier: commentIdentifiers[0],
|
|
106
105
|
text: texts[0],
|
|
107
106
|
timestamp: timestamps[0],
|
|
108
107
|
originalTransactionId: originalTransactionHashes[0]
|
|
@@ -111,7 +110,7 @@ contract CommentsTest is CommentsTestBase {
|
|
|
111
110
|
// verify second comment is emitted
|
|
112
111
|
emit IComments.BackfilledComment({
|
|
113
112
|
commentId: comments.hashCommentIdentifier(commentIdentifiers[1]),
|
|
114
|
-
|
|
113
|
+
commentIdentifier: commentIdentifiers[1],
|
|
115
114
|
text: texts[1],
|
|
116
115
|
timestamp: timestamps[1],
|
|
117
116
|
originalTransactionId: originalTransactionHashes[1]
|
|
@@ -221,7 +220,7 @@ contract CommentsTest is CommentsTestBase {
|
|
|
221
220
|
comments.sparkComment{value: SPARKS_VALUE}(commentIdentifier, 1, address(0));
|
|
222
221
|
}
|
|
223
222
|
|
|
224
|
-
function testCommentSparkCommentValid(
|
|
223
|
+
function testCommentSparkCommentValid(uint256 sparksQuantity) public {
|
|
225
224
|
vm.assume(sparksQuantity > 0 && sparksQuantity < 1_000_000_000_000_000);
|
|
226
225
|
|
|
227
226
|
// comment
|
|
@@ -229,16 +228,23 @@ contract CommentsTest is CommentsTestBase {
|
|
|
229
228
|
IComments.CommentIdentifier memory commentIdentifier = _mockComment(collectorWithToken, replyTo);
|
|
230
229
|
|
|
231
230
|
// mint
|
|
232
|
-
address
|
|
231
|
+
address commenter2 = makeAddr("commenter2");
|
|
233
232
|
|
|
234
233
|
uint256 zoraRecipientBalanceBeforeSpark = protocolRewards.balanceOf(zoraRecipient);
|
|
235
234
|
|
|
236
235
|
// spark comment
|
|
237
|
-
vm.deal(
|
|
236
|
+
vm.deal(commenter2, sparksQuantity * SPARKS_VALUE);
|
|
238
237
|
|
|
239
238
|
vm.expectEmit(true, true, true, true);
|
|
240
|
-
emit IComments.SparkedComment(
|
|
241
|
-
|
|
239
|
+
emit IComments.SparkedComment(
|
|
240
|
+
comments.hashCommentIdentifier(commentIdentifier),
|
|
241
|
+
commentIdentifier,
|
|
242
|
+
sparksQuantity,
|
|
243
|
+
commenter2,
|
|
244
|
+
block.timestamp,
|
|
245
|
+
address(0)
|
|
246
|
+
);
|
|
247
|
+
vm.prank(commenter2);
|
|
242
248
|
comments.sparkComment{value: sparksQuantity * SPARKS_VALUE}(commentIdentifier, sparksQuantity, address(0));
|
|
243
249
|
|
|
244
250
|
uint256 zoraReward = (sparksQuantity * SPARKS_VALUE * (ZORA_REWARD_PCT + REFERRER_REWARD_PCT)) / BPS_TO_PERCENT_2_DECIMAL_PERCISION;
|
|
@@ -246,7 +252,7 @@ contract CommentsTest is CommentsTestBase {
|
|
|
246
252
|
vm.assertEq(protocolRewards.balanceOf(collectorWithToken), (sparksQuantity * SPARKS_VALUE) - zoraReward);
|
|
247
253
|
}
|
|
248
254
|
|
|
249
|
-
function testCommentSparkCommentValidWithReferrer(
|
|
255
|
+
function testCommentSparkCommentValidWithReferrer(uint256 sparksQuantity) public {
|
|
250
256
|
vm.assume(sparksQuantity > 0 && sparksQuantity < 1_000_000_000_000_000);
|
|
251
257
|
|
|
252
258
|
// comment
|
|
@@ -254,18 +260,25 @@ contract CommentsTest is CommentsTestBase {
|
|
|
254
260
|
IComments.CommentIdentifier memory commentIdentifier = _mockComment(collectorWithToken, replyTo);
|
|
255
261
|
|
|
256
262
|
// mint
|
|
257
|
-
address
|
|
263
|
+
address commenter2 = makeAddr("commenter2");
|
|
258
264
|
|
|
259
265
|
uint256 zoraRecipientBalanceBeforeSpark = protocolRewards.balanceOf(zoraRecipient);
|
|
260
266
|
|
|
261
267
|
// spark comment
|
|
262
|
-
vm.deal(
|
|
268
|
+
vm.deal(commenter2, sparksQuantity * SPARKS_VALUE);
|
|
263
269
|
|
|
264
270
|
address referrer = makeAddr("referrer");
|
|
265
271
|
|
|
266
272
|
vm.expectEmit(true, true, true, true);
|
|
267
|
-
emit IComments.SparkedComment(
|
|
268
|
-
|
|
273
|
+
emit IComments.SparkedComment(
|
|
274
|
+
comments.hashCommentIdentifier(commentIdentifier),
|
|
275
|
+
commentIdentifier,
|
|
276
|
+
sparksQuantity,
|
|
277
|
+
commenter2,
|
|
278
|
+
block.timestamp,
|
|
279
|
+
referrer
|
|
280
|
+
);
|
|
281
|
+
vm.prank(commenter2);
|
|
269
282
|
comments.sparkComment{value: sparksQuantity * SPARKS_VALUE}(commentIdentifier, sparksQuantity, referrer);
|
|
270
283
|
|
|
271
284
|
uint256 zoraReward = (sparksQuantity * SPARKS_VALUE * ZORA_REWARD_PCT) / BPS_TO_PERCENT_2_DECIMAL_PERCISION;
|
|
@@ -294,7 +307,7 @@ contract CommentsTest is CommentsTestBase {
|
|
|
294
307
|
IComments.CommentIdentifier memory replyTo
|
|
295
308
|
) internal returns (IComments.CommentIdentifier memory) {
|
|
296
309
|
vm.prank(commenter);
|
|
297
|
-
return comments.comment{value: SPARKS_VALUE}(commenter, contractAddress, tokenId, content, replyTo, address(0));
|
|
310
|
+
return comments.comment{value: SPARKS_VALUE}(commenter, contractAddress, tokenId, content, replyTo, address(0), address(0));
|
|
298
311
|
}
|
|
299
312
|
|
|
300
313
|
function testHashAndCheckCommentExists() public {
|
|
@@ -318,8 +331,8 @@ contract CommentsTest is CommentsTestBase {
|
|
|
318
331
|
}
|
|
319
332
|
|
|
320
333
|
function testReplyToNonExistentComment() public {
|
|
321
|
-
address
|
|
322
|
-
_setupCommenterWithTokenAndSparks(
|
|
334
|
+
address commenter = makeAddr("commenter");
|
|
335
|
+
_setupCommenterWithTokenAndSparks(commenter, 1);
|
|
323
336
|
|
|
324
337
|
IComments.CommentIdentifier memory nonExistentReplyTo = IComments.CommentIdentifier({
|
|
325
338
|
commenter: makeAddr("nonExistentCommenter"),
|
|
@@ -329,7 +342,7 @@ contract CommentsTest is CommentsTestBase {
|
|
|
329
342
|
});
|
|
330
343
|
|
|
331
344
|
vm.expectRevert(IComments.CommentDoesntExist.selector);
|
|
332
|
-
postComment(
|
|
345
|
+
postComment(commenter, address(mock1155), tokenId1, "Replying to non-existent comment", nonExistentReplyTo);
|
|
333
346
|
}
|
|
334
347
|
|
|
335
348
|
function testReplyToCommentThatAddressDoesNotMatch() public {
|
|
@@ -354,7 +367,15 @@ contract CommentsTest is CommentsTestBase {
|
|
|
354
367
|
abi.encodeWithSelector(IComments.CommentAddressOrTokenIdsDoNotMatch.selector, mismatchedAddress, tokenId1, address(mock1155), tokenId1)
|
|
355
368
|
);
|
|
356
369
|
vm.prank(replier);
|
|
357
|
-
comments.comment{value: SPARKS_VALUE}(
|
|
370
|
+
comments.comment{value: SPARKS_VALUE}(
|
|
371
|
+
replier,
|
|
372
|
+
mismatchedAddress,
|
|
373
|
+
tokenId1,
|
|
374
|
+
"Reply to original comment",
|
|
375
|
+
originalCommentIdentifier,
|
|
376
|
+
address(0),
|
|
377
|
+
address(0)
|
|
378
|
+
);
|
|
358
379
|
|
|
359
380
|
// mismatched tokenId
|
|
360
381
|
uint256 mismatchedTokenId = 123;
|
|
@@ -369,6 +390,7 @@ contract CommentsTest is CommentsTestBase {
|
|
|
369
390
|
mismatchedTokenId,
|
|
370
391
|
"Reply to original comment",
|
|
371
392
|
originalCommentIdentifier,
|
|
393
|
+
address(0),
|
|
372
394
|
address(0)
|
|
373
395
|
);
|
|
374
396
|
}
|
|
@@ -412,7 +434,7 @@ contract CommentsTest is CommentsTestBase {
|
|
|
412
434
|
|
|
413
435
|
assertEq(payable(address(comments)).balance, 0, "comments contract should have no balance");
|
|
414
436
|
|
|
415
|
-
|
|
437
|
+
uint256 commenteeSparks = comments.commentSparksQuantity(originalCommentIdentifier);
|
|
416
438
|
assertEq(commenteeSparks, 0, "commentee sparks should be 0");
|
|
417
439
|
|
|
418
440
|
assertEq(protocolRewards.balanceOf(originalCommenter), (SPARKS_VALUE * 70) / 100, "rewards mismatch");
|
|
@@ -429,7 +451,15 @@ contract CommentsTest is CommentsTestBase {
|
|
|
429
451
|
|
|
430
452
|
vm.expectRevert(abi.encodeWithSelector(IComments.CommenterMismatch.selector, mismatchedCommenter, actualCommenter));
|
|
431
453
|
vm.prank(actualCommenter);
|
|
432
|
-
comments.comment{value: SPARKS_VALUE}(
|
|
454
|
+
comments.comment{value: SPARKS_VALUE}(
|
|
455
|
+
mismatchedCommenter,
|
|
456
|
+
address(mock1155),
|
|
457
|
+
tokenId1,
|
|
458
|
+
"Mismatched commenter",
|
|
459
|
+
emptyCommentIdentifier,
|
|
460
|
+
address(0),
|
|
461
|
+
address(0)
|
|
462
|
+
);
|
|
433
463
|
}
|
|
434
464
|
|
|
435
465
|
function testRevertOnEmptyComment() public {
|
|
@@ -458,7 +488,7 @@ contract CommentsTest is CommentsTestBase {
|
|
|
458
488
|
vm.deal(tokenHolder, 1 ether);
|
|
459
489
|
vm.prank(tokenHolder);
|
|
460
490
|
vm.expectRevert(abi.encodeWithSelector(IComments.IncorrectETHAmountForSparks.selector, 1 ether, SPARKS_VALUE));
|
|
461
|
-
comments.comment{value: 1 ether}(tokenHolder, address(mock1155), tokenId1, "test", emptyCommentIdentifier, address(0));
|
|
491
|
+
comments.comment{value: 1 ether}(tokenHolder, address(mock1155), tokenId1, "test", emptyCommentIdentifier, address(0), address(0));
|
|
462
492
|
}
|
|
463
493
|
|
|
464
494
|
function testCommentRevertsWhenSendTooLittleValue() public {
|
|
@@ -468,7 +498,7 @@ contract CommentsTest is CommentsTestBase {
|
|
|
468
498
|
|
|
469
499
|
vm.prank(tokenHolder);
|
|
470
500
|
vm.expectRevert(abi.encodeWithSelector(IComments.MustSendAtLeastOneSpark.selector));
|
|
471
|
-
comments.comment(tokenHolder, address(mock1155), tokenId1, "test", emptyCommentIdentifier, address(0));
|
|
501
|
+
comments.comment(tokenHolder, address(mock1155), tokenId1, "test", emptyCommentIdentifier, address(0), address(0));
|
|
472
502
|
}
|
|
473
503
|
|
|
474
504
|
function testCommentRevertsWhenSendExactValue() public {
|
|
@@ -477,6 +507,113 @@ contract CommentsTest is CommentsTestBase {
|
|
|
477
507
|
_setupCommenterWithTokenAndSparks(tokenHolder, 1);
|
|
478
508
|
|
|
479
509
|
vm.prank(tokenHolder);
|
|
480
|
-
comments.comment{value: SPARKS_VALUE}(tokenHolder, address(mock1155), tokenId1, "test", emptyCommentIdentifier, address(0));
|
|
510
|
+
comments.comment{value: SPARKS_VALUE}(tokenHolder, address(mock1155), tokenId1, "test", emptyCommentIdentifier, address(0), address(0));
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
function testCommentWithMock1155NoCreatorRewardRecipient() public {
|
|
514
|
+
Mock1155NoCreatorRewardRecipient mock1155NoCreatorRewardRecipient = new Mock1155NoCreatorRewardRecipient();
|
|
515
|
+
mock1155NoCreatorRewardRecipient.createToken(tokenId1, tokenAdmin);
|
|
516
|
+
|
|
517
|
+
vm.startPrank(collectorWithToken);
|
|
518
|
+
mock1155NoCreatorRewardRecipient.mint(collectorWithToken, tokenId1, 1, "");
|
|
519
|
+
vm.stopPrank();
|
|
520
|
+
|
|
521
|
+
uint256 sparksQuantity = 1;
|
|
522
|
+
|
|
523
|
+
vm.deal(collectorWithToken, sparksQuantity * SPARKS_VALUE);
|
|
524
|
+
|
|
525
|
+
address contractAddress = address(mock1155NoCreatorRewardRecipient);
|
|
526
|
+
uint256 tokenId = tokenId1;
|
|
527
|
+
|
|
528
|
+
// blank replyTo
|
|
529
|
+
IComments.CommentIdentifier memory replyTo;
|
|
530
|
+
|
|
531
|
+
// funds recipient is 0x000...
|
|
532
|
+
vm.prank(collectorWithToken);
|
|
533
|
+
vm.expectRevert(abi.encodeWithSelector(IComments.NoFundsRecipient.selector));
|
|
534
|
+
comments.comment{value: sparksQuantity * SPARKS_VALUE}(collectorWithToken, contractAddress, tokenId, "test comment", replyTo, address(0), address(0));
|
|
535
|
+
|
|
536
|
+
// with funds recipient set
|
|
537
|
+
address newFundsRecipient = makeAddr("newFundsRecipient");
|
|
538
|
+
mock1155NoCreatorRewardRecipient.setFundsRecipient(payable(newFundsRecipient));
|
|
539
|
+
vm.deal(collectorWithToken, sparksQuantity * SPARKS_VALUE);
|
|
540
|
+
|
|
541
|
+
vm.prank(collectorWithToken);
|
|
542
|
+
comments.comment{value: sparksQuantity * SPARKS_VALUE}(
|
|
543
|
+
collectorWithToken,
|
|
544
|
+
contractAddress,
|
|
545
|
+
tokenId,
|
|
546
|
+
"test comment with recipient",
|
|
547
|
+
replyTo,
|
|
548
|
+
address(0),
|
|
549
|
+
address(0)
|
|
550
|
+
);
|
|
551
|
+
|
|
552
|
+
uint256 zoraReward = (sparksQuantity * SPARKS_VALUE * (ZORA_REWARD_PCT + REFERRER_REWARD_PCT)) / BPS_TO_PERCENT_2_DECIMAL_PERCISION;
|
|
553
|
+
uint256 recipientReward = (sparksQuantity * SPARKS_VALUE) - zoraReward;
|
|
554
|
+
vm.assertEq(protocolRewards.balanceOf(newFundsRecipient), recipientReward);
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
function testCommentWithMock1155NoOwner() public {
|
|
558
|
+
Mock1155NoOwner mock1155NoOwner = new Mock1155NoOwner();
|
|
559
|
+
mock1155NoOwner.createToken(tokenId1, tokenAdmin);
|
|
560
|
+
|
|
561
|
+
vm.startPrank(collectorWithToken);
|
|
562
|
+
mock1155NoOwner.mint(collectorWithToken, tokenId1, 1, "");
|
|
563
|
+
vm.stopPrank();
|
|
564
|
+
|
|
565
|
+
uint256 sparksQuantity = 1;
|
|
566
|
+
vm.deal(collectorWithToken, sparksQuantity * SPARKS_VALUE);
|
|
567
|
+
|
|
568
|
+
address contractAddress = address(mock1155NoOwner);
|
|
569
|
+
uint256 tokenId = tokenId1;
|
|
570
|
+
|
|
571
|
+
IComments.CommentIdentifier memory replyTo;
|
|
572
|
+
|
|
573
|
+
vm.prank(collectorWithToken);
|
|
574
|
+
vm.expectRevert(abi.encodeWithSelector(IComments.NoFundsRecipient.selector));
|
|
575
|
+
comments.comment{value: sparksQuantity * SPARKS_VALUE}(collectorWithToken, contractAddress, tokenId, "test comment", replyTo, address(0), address(0));
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
function testImplementation() public view {
|
|
579
|
+
assertEq(comments.implementation(), address(commentsImpl));
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
function testCommentsConstructorAddressZero() public {
|
|
583
|
+
vm.expectRevert(abi.encodeWithSelector(IComments.AddressZero.selector));
|
|
584
|
+
new CommentsImpl(SPARKS_VALUE, address(0), zoraRecipient);
|
|
585
|
+
|
|
586
|
+
vm.expectRevert(abi.encodeWithSelector(IComments.AddressZero.selector));
|
|
587
|
+
new CommentsImpl(SPARKS_VALUE, address(protocolRewards), address(0));
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
function testCommentsInitializeAddressZero() public {
|
|
591
|
+
CommentsImpl implTest = new CommentsImpl(SPARKS_VALUE, address(protocolRewards), zoraRecipient);
|
|
592
|
+
address[] memory delegateCommenters = new address[](0);
|
|
593
|
+
|
|
594
|
+
CommentsImpl commentsProxyTest = CommentsImpl(payable(address(new Comments(address(implTest)))));
|
|
595
|
+
vm.expectRevert(abi.encodeWithSelector(IComments.AddressZero.selector));
|
|
596
|
+
commentsProxyTest.initialize({defaultAdmin: address(0), backfiller: commentsBackfiller, delegateCommenters: delegateCommenters});
|
|
597
|
+
|
|
598
|
+
vm.expectRevert(abi.encodeWithSelector(IComments.AddressZero.selector));
|
|
599
|
+
commentsProxyTest.initialize({defaultAdmin: commentsAdmin, backfiller: address(0), delegateCommenters: new address[](0)});
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
function testGrantRoleWithBackfillRole() public {
|
|
603
|
+
address newBackfiller = makeAddr("newBackfiller");
|
|
604
|
+
bytes32 BACKFILLER_ROLE = keccak256("BACKFILLER_ROLE");
|
|
605
|
+
vm.prank(commentsAdmin);
|
|
606
|
+
comments.grantRole(BACKFILLER_ROLE, newBackfiller);
|
|
607
|
+
vm.assertEq(comments.hasRole(BACKFILLER_ROLE, newBackfiller), true);
|
|
608
|
+
|
|
609
|
+
vm.prank(commentsAdmin);
|
|
610
|
+
comments.revokeRole(BACKFILLER_ROLE, newBackfiller);
|
|
611
|
+
vm.assertEq(comments.hasRole(BACKFILLER_ROLE, newBackfiller), false);
|
|
612
|
+
|
|
613
|
+
address notAdmin = makeAddr("notAdmin");
|
|
614
|
+
bytes32 no_role;
|
|
615
|
+
vm.prank(notAdmin);
|
|
616
|
+
vm.expectRevert(abi.encodeWithSignature("AccessControlUnauthorizedAccount(address,bytes32)", notAdmin, no_role));
|
|
617
|
+
comments.grantRole(BACKFILLER_ROLE, newBackfiller);
|
|
481
618
|
}
|
|
482
619
|
}
|
|
@@ -7,11 +7,11 @@ import {CommentsImpl} from "../src/CommentsImpl.sol";
|
|
|
7
7
|
import {Comments} from "../src/proxy/Comments.sol";
|
|
8
8
|
import {IComments} from "../src/interfaces/IComments.sol";
|
|
9
9
|
import {Mock1155} from "./mocks/Mock1155.sol";
|
|
10
|
-
import {IProtocolRewards} from "@zoralabs/protocol-rewards/src/interfaces/IProtocolRewards.sol";
|
|
11
10
|
import {ProtocolRewards} from "./mocks/ProtocolRewards.sol";
|
|
12
11
|
|
|
13
12
|
contract CommentsTestBase is Test {
|
|
14
13
|
CommentsImpl internal comments;
|
|
14
|
+
CommentsImpl internal commentsImpl;
|
|
15
15
|
Mock1155 internal mock1155;
|
|
16
16
|
|
|
17
17
|
uint256 internal constant SPARKS_VALUE = 0.000001 ether;
|
|
@@ -22,7 +22,8 @@ contract CommentsTestBase is Test {
|
|
|
22
22
|
address internal commentsAdmin = makeAddr("commentsAdmin");
|
|
23
23
|
address internal commentsBackfiller = makeAddr("commentsBackfiller");
|
|
24
24
|
address internal zoraRecipient = makeAddr("zoraRecipient");
|
|
25
|
-
address internal tokenAdmin
|
|
25
|
+
address internal tokenAdmin;
|
|
26
|
+
uint256 internal tokenAdminPrivateKey;
|
|
26
27
|
address internal collectorWithToken;
|
|
27
28
|
uint256 internal collectorWithTokenPrivateKey;
|
|
28
29
|
address internal collectorWithoutToken = makeAddr("collectorWithoutToken");
|
|
@@ -34,32 +35,23 @@ contract CommentsTestBase is Test {
|
|
|
34
35
|
|
|
35
36
|
function setUp() public {
|
|
36
37
|
protocolRewards = new ProtocolRewards();
|
|
37
|
-
|
|
38
|
+
commentsImpl = new CommentsImpl(SPARKS_VALUE, address(protocolRewards), zoraRecipient);
|
|
38
39
|
|
|
39
40
|
// initialze empty delegateCommenters array
|
|
40
41
|
address[] memory delegateCommenters = new address[](0);
|
|
41
42
|
|
|
42
43
|
// intialize proxy
|
|
43
44
|
comments = CommentsImpl(payable(address(new Comments(address(commentsImpl)))));
|
|
44
|
-
comments.initialize({
|
|
45
|
-
_zoraRecipient: zoraRecipient,
|
|
46
|
-
defaultAdmin: commentsAdmin,
|
|
47
|
-
backfiller: commentsBackfiller,
|
|
48
|
-
delegateCommenters: delegateCommenters
|
|
49
|
-
});
|
|
45
|
+
comments.initialize({defaultAdmin: commentsAdmin, backfiller: commentsBackfiller, delegateCommenters: delegateCommenters});
|
|
50
46
|
|
|
51
47
|
mock1155 = new Mock1155();
|
|
48
|
+
(tokenAdmin, tokenAdminPrivateKey) = makeAddrAndKey("tokenAdmin");
|
|
52
49
|
|
|
53
50
|
mock1155.createToken(tokenId1, tokenAdmin);
|
|
54
51
|
mock1155.createToken(tokenId2, tokenAdmin);
|
|
55
52
|
|
|
56
53
|
(collectorWithToken, collectorWithTokenPrivateKey) = makeAddrAndKey("collectorWithToken");
|
|
57
54
|
(sparker, sparkerPrivateKey) = makeAddrAndKey("sparker");
|
|
58
|
-
|
|
59
|
-
mock1155 = new Mock1155();
|
|
60
|
-
|
|
61
|
-
mock1155.createToken(tokenId1, tokenAdmin);
|
|
62
|
-
mock1155.createToken(tokenId2, tokenAdmin);
|
|
63
55
|
}
|
|
64
56
|
|
|
65
57
|
function _expectedCommentIdentifier(
|
|
@@ -71,16 +63,16 @@ contract CommentsTestBase is Test {
|
|
|
71
63
|
}
|
|
72
64
|
|
|
73
65
|
function _mockComment(
|
|
74
|
-
address
|
|
66
|
+
address commenter,
|
|
75
67
|
IComments.CommentIdentifier memory replyTo
|
|
76
68
|
) internal returns (IComments.CommentIdentifier memory commentIdentifier) {
|
|
77
|
-
vm.startPrank(
|
|
78
|
-
mock1155.mint(
|
|
69
|
+
vm.startPrank(commenter);
|
|
70
|
+
mock1155.mint(commenter, tokenId1, 1, "");
|
|
79
71
|
vm.stopPrank();
|
|
80
72
|
|
|
81
|
-
vm.deal(
|
|
73
|
+
vm.deal(commenter, SPARKS_VALUE);
|
|
82
74
|
|
|
83
|
-
vm.prank(
|
|
84
|
-
commentIdentifier = comments.comment{value: SPARKS_VALUE}(
|
|
75
|
+
vm.prank(commenter);
|
|
76
|
+
commentIdentifier = comments.comment{value: SPARKS_VALUE}(commenter, address(mock1155), tokenId1, "comment", replyTo, address(0), address(0));
|
|
85
77
|
}
|
|
86
78
|
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.20;
|
|
3
|
+
|
|
4
|
+
import "forge-std/Test.sol";
|
|
5
|
+
|
|
6
|
+
import {CommentsImpl} from "../src/CommentsImpl.sol";
|
|
7
|
+
import {Comments} from "../src/proxy/Comments.sol";
|
|
8
|
+
import {IComments} from "../src/interfaces/IComments.sol";
|
|
9
|
+
import {Mock1155} from "./mocks/Mock1155.sol";
|
|
10
|
+
import {MockDelegateCommenter} from "./mocks/MockDelegateCommenter.sol";
|
|
11
|
+
|
|
12
|
+
contract Comments_mintAndCommentTest is Test {
|
|
13
|
+
Mock1155 mock1155;
|
|
14
|
+
CommentsImpl comments;
|
|
15
|
+
|
|
16
|
+
uint256 constant SPARKS_VALUE = 0.000001 ether;
|
|
17
|
+
|
|
18
|
+
address zoraRecipient = makeAddr("zoraRecipient");
|
|
19
|
+
address commentsAdmin = makeAddr("commentsAdmin");
|
|
20
|
+
address commenter = makeAddr("commenter");
|
|
21
|
+
address tokenAdmin = makeAddr("tokenAdmin");
|
|
22
|
+
address backfiller = makeAddr("backfiller");
|
|
23
|
+
address referrer = makeAddr("referrer");
|
|
24
|
+
|
|
25
|
+
uint256 internal constant ZORA_REWARD_PCT = 10;
|
|
26
|
+
uint256 internal constant REFERRER_REWARD_PCT = 20;
|
|
27
|
+
uint256 internal constant BPS_TO_PERCENT_2_DECIMAL_PERCISION = 100;
|
|
28
|
+
|
|
29
|
+
uint256 tokenId1 = 1;
|
|
30
|
+
|
|
31
|
+
address constant protocolRewards = 0x7777777F279eba3d3Ad8F4E708545291A6fDBA8B;
|
|
32
|
+
MockDelegateCommenter mockDelegateCommenter;
|
|
33
|
+
|
|
34
|
+
function setUp() public {
|
|
35
|
+
vm.createSelectFork("zora_sepolia", 14562731);
|
|
36
|
+
|
|
37
|
+
CommentsImpl commentsImpl = new CommentsImpl(SPARKS_VALUE, protocolRewards, zoraRecipient);
|
|
38
|
+
|
|
39
|
+
comments = CommentsImpl(payable(address(new Comments(address(commentsImpl)))));
|
|
40
|
+
|
|
41
|
+
mockDelegateCommenter = new MockDelegateCommenter(address(comments));
|
|
42
|
+
|
|
43
|
+
address[] memory delegateCommenters = new address[](1);
|
|
44
|
+
delegateCommenters[0] = address(mockDelegateCommenter);
|
|
45
|
+
comments.initialize({defaultAdmin: commentsAdmin, backfiller: backfiller, delegateCommenters: delegateCommenters});
|
|
46
|
+
|
|
47
|
+
mock1155 = new Mock1155();
|
|
48
|
+
|
|
49
|
+
mock1155.createToken(tokenId1, tokenAdmin);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function _expectedCommentIdentifier(
|
|
53
|
+
address _commenter,
|
|
54
|
+
address contractAddress,
|
|
55
|
+
uint256 tokenId
|
|
56
|
+
) internal view returns (IComments.CommentIdentifier memory) {
|
|
57
|
+
return IComments.CommentIdentifier({commenter: _commenter, contractAddress: contractAddress, tokenId: tokenId, nonce: comments.nextNonce()});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function testCanDelegateCommentWithSparks() public {
|
|
61
|
+
uint256 quantityToMint = 1;
|
|
62
|
+
uint256 mintFee = 0.000111 ether;
|
|
63
|
+
|
|
64
|
+
address contractAddress = address(mock1155);
|
|
65
|
+
uint256 tokenId = tokenId1;
|
|
66
|
+
|
|
67
|
+
IComments.CommentIdentifier memory emptyReplyTo;
|
|
68
|
+
|
|
69
|
+
IComments.CommentIdentifier memory expectedCommentIdentifier = _expectedCommentIdentifier(commenter, contractAddress, tokenId);
|
|
70
|
+
|
|
71
|
+
bytes32 expectedCommentId = comments.hashCommentIdentifier(expectedCommentIdentifier);
|
|
72
|
+
bytes32 expectedReplyToId = bytes32(0);
|
|
73
|
+
|
|
74
|
+
vm.deal(commenter, mintFee * quantityToMint + SPARKS_VALUE);
|
|
75
|
+
vm.expectEmit(true, true, true, true);
|
|
76
|
+
emit IComments.Commented(
|
|
77
|
+
expectedCommentId,
|
|
78
|
+
_expectedCommentIdentifier(commenter, contractAddress, tokenId),
|
|
79
|
+
expectedReplyToId,
|
|
80
|
+
emptyReplyTo,
|
|
81
|
+
1,
|
|
82
|
+
"test",
|
|
83
|
+
block.timestamp,
|
|
84
|
+
referrer
|
|
85
|
+
);
|
|
86
|
+
vm.prank(commenter);
|
|
87
|
+
mockDelegateCommenter.mintAndCommentWithSpark{value: SPARKS_VALUE + mintFee * quantityToMint}({
|
|
88
|
+
quantity: quantityToMint,
|
|
89
|
+
collection: address(mock1155),
|
|
90
|
+
tokenId: tokenId1,
|
|
91
|
+
comment: "test",
|
|
92
|
+
referrer: referrer,
|
|
93
|
+
sparksQuantity: 1
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
// validate that the protocol creator received rewards
|
|
97
|
+
uint256 zoraReward = (SPARKS_VALUE * (ZORA_REWARD_PCT)) / BPS_TO_PERCENT_2_DECIMAL_PERCISION;
|
|
98
|
+
uint256 referrerReward = (SPARKS_VALUE * (REFERRER_REWARD_PCT)) / BPS_TO_PERCENT_2_DECIMAL_PERCISION;
|
|
99
|
+
vm.assertEq(comments.protocolRewards().balanceOf(zoraRecipient), zoraReward);
|
|
100
|
+
vm.assertEq(comments.protocolRewards().balanceOf(referrer), referrerReward);
|
|
101
|
+
vm.assertEq(comments.protocolRewards().balanceOf(tokenAdmin), SPARKS_VALUE - zoraReward - referrerReward);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function testDelegateCommentRevertsWhenMoreThanOneSpark() public {
|
|
105
|
+
uint256 quantityToMint = 1;
|
|
106
|
+
uint256 mintFee = 0.000111 ether;
|
|
107
|
+
|
|
108
|
+
uint256 sparksQuantity = 2;
|
|
109
|
+
vm.deal(commenter, mintFee * quantityToMint + SPARKS_VALUE * sparksQuantity);
|
|
110
|
+
|
|
111
|
+
vm.prank(commenter);
|
|
112
|
+
vm.expectRevert(abi.encodeWithSelector(IComments.IncorrectETHAmountForSparks.selector, SPARKS_VALUE * sparksQuantity, SPARKS_VALUE));
|
|
113
|
+
mockDelegateCommenter.mintAndCommentWithSpark{value: SPARKS_VALUE * sparksQuantity + mintFee * quantityToMint}({
|
|
114
|
+
quantity: quantityToMint,
|
|
115
|
+
collection: address(mock1155),
|
|
116
|
+
tokenId: tokenId1,
|
|
117
|
+
comment: "test",
|
|
118
|
+
referrer: referrer,
|
|
119
|
+
sparksQuantity: sparksQuantity
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function test_delegateComment_revertsWhenNotOwnerOrCreator() public {
|
|
124
|
+
address notOwner = makeAddr("notOwner");
|
|
125
|
+
vm.prank(notOwner);
|
|
126
|
+
vm.expectRevert(IComments.NotTokenHolderOrAdmin.selector);
|
|
127
|
+
mockDelegateCommenter.forwardComment(address(mock1155), tokenId1, "test");
|
|
128
|
+
}
|
|
129
|
+
}
|