mirror of
https://github.com/lens-protocol/core.git
synced 2026-04-22 03:02:03 -04:00
test: Publication tests base architecture added
This commit is contained in:
@@ -1,196 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.13;
|
||||
|
||||
import 'test/foundry/base/BaseTest.t.sol';
|
||||
import 'test/foundry/helpers/SignatureHelpers.sol';
|
||||
import 'test/foundry/helpers/CollectingHelpers.sol';
|
||||
import 'test/foundry/MetaTxNegatives.t.sol';
|
||||
|
||||
// TODO: We still need these collecting tests to work with Deprecated collect modules in V1 posts
|
||||
// TODO add check for _initialize() called for fork tests - check name and symbol set
|
||||
|
||||
contract CollectingTest is BaseTest, CollectingHelpers, SigSetup {
|
||||
uint256 constant collectorProfileOwnerPk = 0xC011EEC7012;
|
||||
address collectorProfileOwner;
|
||||
uint256 collectorProfileId;
|
||||
|
||||
uint256 constant userWithoutProfilePk = 0x105312;
|
||||
address userWithoutProfile;
|
||||
|
||||
function setUp() public virtual override(SigSetup, TestSetup) {
|
||||
TestSetup.setUp();
|
||||
SigSetup.setUp();
|
||||
|
||||
vm.prank(profileOwner);
|
||||
hub.post(mockPostParams);
|
||||
|
||||
collectorProfileOwner = vm.addr(collectorProfileOwnerPk);
|
||||
collectorProfileId = _createProfile(collectorProfileOwner);
|
||||
|
||||
userWithoutProfile = vm.addr(userWithoutProfilePk);
|
||||
|
||||
mockCollectParams.collectorProfileId = collectorProfileId;
|
||||
}
|
||||
|
||||
function _collect(
|
||||
uint256, /* metaTxSignerPk */
|
||||
address transactionExecutor,
|
||||
Types.CollectParams memory collectParams
|
||||
) internal virtual returns (uint256) {
|
||||
vm.prank(transactionExecutor);
|
||||
return hub.collect(collectParams);
|
||||
}
|
||||
|
||||
// NEGATIVES
|
||||
|
||||
// Also acts like a test for cannot collect specifying another (non-owned) profile as a parameter
|
||||
function testCannotCollectIfNotDelegatedExecutor() public {
|
||||
vm.expectRevert(Errors.ExecutorInvalid.selector);
|
||||
_collect(collectorProfileOwnerPk, otherSigner, mockCollectParams);
|
||||
}
|
||||
|
||||
function testCannotCollectIfNonexistantPub() public {
|
||||
mockCollectParams.publicationCollectedId = 2;
|
||||
// Check that the publication doesn't exist.
|
||||
assertEq(
|
||||
_getPub(mockCollectParams.publicationCollectedProfileId, mockCollectParams.publicationCollectedId)
|
||||
.pointedProfileId,
|
||||
0
|
||||
);
|
||||
|
||||
vm.expectRevert(Errors.CollectNotAllowed.selector);
|
||||
_collect(collectorProfileOwnerPk, collectorProfileOwner, mockCollectParams);
|
||||
vm.stopPrank();
|
||||
}
|
||||
|
||||
function testCannotCollectIfZeroPub() public {
|
||||
mockCollectParams.publicationCollectedId = 0;
|
||||
// Check that the publication doesn't exist.
|
||||
assertEq(
|
||||
_getPub(mockCollectParams.publicationCollectedProfileId, mockCollectParams.publicationCollectedId)
|
||||
.pointedProfileId,
|
||||
0
|
||||
);
|
||||
|
||||
vm.expectRevert(Errors.CollectNotAllowed.selector);
|
||||
_collect(collectorProfileOwnerPk, collectorProfileOwner, mockCollectParams);
|
||||
vm.stopPrank();
|
||||
}
|
||||
|
||||
function testCannotCollect_WithoutProfile() public {
|
||||
mockCollectParams.collectorProfileId = _getNextProfileId(); // Non-existent profile
|
||||
vm.expectRevert(Errors.TokenDoesNotExist.selector);
|
||||
_collect(userWithoutProfilePk, userWithoutProfile, mockCollectParams);
|
||||
vm.stopPrank();
|
||||
}
|
||||
|
||||
function testCannotCollectIfBlocked() public {
|
||||
vm.prank(profileOwner);
|
||||
hub.setBlockStatus(newProfileId, _toUint256Array(collectorProfileId), _toBoolArray(true));
|
||||
vm.expectRevert(Errors.Blocked.selector);
|
||||
_collect(collectorProfileOwnerPk, collectorProfileOwner, mockCollectParams);
|
||||
}
|
||||
|
||||
function testCannotCollectMirror() public {
|
||||
_checkCollectNFTBefore();
|
||||
|
||||
// Mirror once
|
||||
vm.prank(profileOwner);
|
||||
uint256 mirrorPubId = hub.mirror(mockMirrorParams);
|
||||
|
||||
// Collecting the mirror
|
||||
mockCollectParams.publicationCollectedId = mirrorPubId;
|
||||
|
||||
vm.expectRevert(Errors.CollectNotAllowed.selector);
|
||||
_collect(collectorProfileOwnerPk, collectorProfileOwner, mockCollectParams);
|
||||
}
|
||||
|
||||
// SCENARIOS
|
||||
|
||||
function testCollect() public {
|
||||
uint256 startNftId = _checkCollectNFTBefore();
|
||||
|
||||
uint256 nftId = _collect(collectorProfileOwnerPk, collectorProfileOwner, mockCollectParams);
|
||||
|
||||
_checkCollectNFTAfter(nftId, startNftId + 1);
|
||||
}
|
||||
|
||||
function testCollectMirror() public {
|
||||
uint256 startNftId = _checkCollectNFTBefore();
|
||||
|
||||
vm.prank(profileOwner);
|
||||
hub.mirror(mockMirrorParams);
|
||||
|
||||
uint256 nftId = _collect(collectorProfileOwnerPk, collectorProfileOwner, mockCollectParams);
|
||||
|
||||
_checkCollectNFTAfter(nftId, startNftId + 1);
|
||||
}
|
||||
|
||||
function testDelegatedExecutorCollect() public {
|
||||
uint256 startNftId = _checkCollectNFTBefore();
|
||||
|
||||
// delegate power to executor
|
||||
_changeDelegatedExecutorsConfig(collectorProfileOwner, collectorProfileId, otherSigner, true);
|
||||
|
||||
// collect from executor
|
||||
uint256 nftId = _collect(otherSignerKey, otherSigner, mockCollectParams);
|
||||
|
||||
_checkCollectNFTAfter(nftId, startNftId + 1);
|
||||
}
|
||||
|
||||
function testDelegatedExecutorCollectMirror() public {
|
||||
uint256 startNftId = _checkCollectNFTBefore();
|
||||
|
||||
// mirror, then delegate power to executor
|
||||
vm.prank(profileOwner);
|
||||
hub.mirror(mockMirrorParams);
|
||||
_changeDelegatedExecutorsConfig(collectorProfileOwner, collectorProfileId, otherSigner, true);
|
||||
|
||||
// collect from executor
|
||||
uint256 nftId = _collect(otherSignerKey, otherSigner, mockCollectParams);
|
||||
|
||||
_checkCollectNFTAfter(nftId, startNftId + 1);
|
||||
}
|
||||
}
|
||||
|
||||
contract CollectingTestMetaTx is CollectingTest, MetaTxNegatives {
|
||||
mapping(address => uint256) cachedNonceByAddress;
|
||||
|
||||
function setUp() public override(CollectingTest, MetaTxNegatives) {
|
||||
CollectingTest.setUp();
|
||||
MetaTxNegatives.setUp();
|
||||
|
||||
cachedNonceByAddress[collectorProfileOwner] = _getSigNonce(collectorProfileOwner);
|
||||
}
|
||||
|
||||
function _collect(
|
||||
uint256 metaTxSignerPk,
|
||||
address transactionExecutor,
|
||||
Types.CollectParams memory collectParams
|
||||
) internal override returns (uint256) {
|
||||
address signer = vm.addr(metaTxSignerPk);
|
||||
uint256 deadline = type(uint256).max;
|
||||
bytes32 digest = _getCollectTypedDataHash(collectParams, cachedNonceByAddress[signer], deadline);
|
||||
return hub.collectWithSig(collectParams, _getSigStruct(transactionExecutor, metaTxSignerPk, digest, deadline));
|
||||
}
|
||||
|
||||
function _executeMetaTx(
|
||||
uint256 signerPk,
|
||||
uint256 nonce,
|
||||
uint256 deadline
|
||||
) internal override {
|
||||
_collectWithSig(
|
||||
mockCollectParams,
|
||||
_getSigStruct(
|
||||
vm.addr(_getDefaultMetaTxSignerPk()),
|
||||
signerPk,
|
||||
_getCollectTypedDataHash(mockCollectParams, nonce, deadline),
|
||||
deadline
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function _getDefaultMetaTxSignerPk() internal pure override returns (uint256) {
|
||||
return collectorProfileOwnerPk;
|
||||
}
|
||||
}
|
||||
@@ -236,28 +236,34 @@ contract EventTest is BaseTest {
|
||||
}
|
||||
|
||||
function testPostingEmitsExpectedEvents() public {
|
||||
vm.prank(profileOwner);
|
||||
uint256 expectedPostId = hub.getPubCount(mockPostParams.profileId) + 1;
|
||||
vm.expectEmit(true, true, false, true, address(hub));
|
||||
emit Events.PostCreated(mockPostParams, 1, _toBytesArray(abi.encode(true)), '', block.timestamp);
|
||||
emit Events.PostCreated(mockPostParams, expectedPostId, _toBytesArray(abi.encode(true)), '', block.timestamp);
|
||||
vm.prank(profileOwner);
|
||||
hub.post(mockPostParams);
|
||||
}
|
||||
|
||||
function testCommentingEmitsExpectedEvents() public {
|
||||
vm.startPrank(profileOwner);
|
||||
hub.post(mockPostParams);
|
||||
uint256 expectedCommentId = hub.getPubCount(mockPostParams.profileId) + 1;
|
||||
vm.expectEmit(true, true, false, true, address(hub));
|
||||
emit Events.CommentCreated(mockCommentParams, 2, '', _toBytesArray(abi.encode(true)), '', block.timestamp);
|
||||
emit Events.CommentCreated(
|
||||
mockCommentParams,
|
||||
expectedCommentId,
|
||||
'',
|
||||
_toBytesArray(abi.encode(true)),
|
||||
'',
|
||||
block.timestamp
|
||||
);
|
||||
vm.prank(profileOwner);
|
||||
hub.comment(mockCommentParams);
|
||||
vm.stopPrank();
|
||||
}
|
||||
|
||||
function testMirroringEmitsExpectedEvents() public {
|
||||
vm.startPrank(profileOwner);
|
||||
hub.post(mockPostParams);
|
||||
uint256 expectedMirrorId = hub.getPubCount(mockPostParams.profileId) + 1;
|
||||
vm.expectEmit(true, true, false, true, address(hub));
|
||||
emit Events.MirrorCreated(mockMirrorParams, 2, '', block.timestamp);
|
||||
emit Events.MirrorCreated(mockMirrorParams, expectedMirrorId, '', block.timestamp);
|
||||
vm.prank(profileOwner);
|
||||
hub.mirror(mockMirrorParams);
|
||||
vm.stopPrank();
|
||||
}
|
||||
|
||||
// TODO: Proper tests for Act
|
||||
|
||||
@@ -1,453 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.13;
|
||||
|
||||
import 'test/foundry/base/BaseTest.t.sol';
|
||||
import 'test/foundry/helpers/SignatureHelpers.sol';
|
||||
import {PublishingHelpers} from 'test/foundry/helpers/PublishingHelpers.sol';
|
||||
|
||||
abstract contract PublishingTest is BaseTest, PublishingHelpers, SigSetup {
|
||||
function replicateInitData() internal virtual {
|
||||
// Default implementation does nothing.
|
||||
}
|
||||
|
||||
function _publish() internal virtual returns (uint256);
|
||||
|
||||
function _publishWithSig(
|
||||
address delegatedSigner,
|
||||
uint256 signerPrivKey,
|
||||
uint256 digestDeadline,
|
||||
uint256 sigDeadline
|
||||
) internal virtual returns (uint256);
|
||||
|
||||
function _publishWithSig(address delegatedSigner, uint256 signerPrivKey) internal virtual returns (uint256) {
|
||||
return _publishWithSig(delegatedSigner, signerPrivKey, deadline, deadline);
|
||||
}
|
||||
|
||||
function _expectedPubFromInitData() internal view virtual returns (Types.Publication memory);
|
||||
|
||||
function setUp() public virtual override(SigSetup, TestSetup) {
|
||||
TestSetup.setUp();
|
||||
SigSetup.setUp();
|
||||
}
|
||||
|
||||
// negatives
|
||||
function testCannotPublishIfNotDelegatedExecutor() public {
|
||||
vm.expectRevert(Errors.ExecutorInvalid.selector);
|
||||
_publish();
|
||||
}
|
||||
|
||||
// TODO: Proper test
|
||||
// function testCannotPublishNotWhitelistedCollectModule() public virtual {
|
||||
// mockPostParams.collectModule = address(0xC0FFEE);
|
||||
// replicateInitData();
|
||||
// vm.prank(profileOwner);
|
||||
// vm.expectRevert(Errors.NotWhitelisted.selector);
|
||||
// _publish();
|
||||
// }
|
||||
|
||||
function testCannotPublishNotWhitelistedReferenceModule() public virtual {
|
||||
mockPostParams.referenceModule = address(0xC0FFEE);
|
||||
replicateInitData();
|
||||
vm.prank(profileOwner);
|
||||
vm.expectRevert(Errors.NotWhitelisted.selector);
|
||||
_publish();
|
||||
}
|
||||
|
||||
// TODO: Proper test
|
||||
// function testCannotPublishWithSigNotWhitelistedCollectModule() public virtual {
|
||||
// mockPostParams.collectModule = address(0xC0FFEE);
|
||||
// replicateInitData();
|
||||
// vm.expectRevert(Errors.NotWhitelisted.selector);
|
||||
// _publishWithSig({delegatedSigner: profileOwner, signerPrivKey: profileOwnerKey});
|
||||
// }
|
||||
|
||||
function testCannotPublishWithSigNotWhitelistedReferenceModule() public virtual {
|
||||
mockPostParams.referenceModule = address(0xC0FFEE);
|
||||
replicateInitData();
|
||||
vm.expectRevert(Errors.NotWhitelisted.selector);
|
||||
_publishWithSig({delegatedSigner: profileOwner, signerPrivKey: profileOwnerKey});
|
||||
}
|
||||
|
||||
function testCannotPublishWithSigInvalidSigner() public {
|
||||
vm.expectRevert(Errors.SignatureInvalid.selector);
|
||||
_publishWithSig({delegatedSigner: profileOwner, signerPrivKey: otherSignerKey});
|
||||
}
|
||||
|
||||
function testCannotPublishWithSigInvalidNonce() public {
|
||||
nonce = _getSigNonce(otherSigner) + 1;
|
||||
vm.expectRevert(Errors.SignatureInvalid.selector);
|
||||
_publishWithSig({delegatedSigner: profileOwner, signerPrivKey: otherSignerKey});
|
||||
}
|
||||
|
||||
function testCannotPublishWithSigInvalidDeadline() public {
|
||||
vm.expectRevert(Errors.SignatureInvalid.selector);
|
||||
_publishWithSig({
|
||||
delegatedSigner: profileOwner,
|
||||
signerPrivKey: profileOwnerKey,
|
||||
digestDeadline: type(uint256).max,
|
||||
sigDeadline: block.timestamp + 10
|
||||
});
|
||||
}
|
||||
|
||||
function testCannotPublishIfNonceWasIncrementedWithAnotherAction() public {
|
||||
assertEq(_getSigNonce(profileOwner), nonce, 'Wrong nonce before posting');
|
||||
|
||||
uint256 expectedPubId = _getPubCount(newProfileId) + 1;
|
||||
|
||||
uint256 pubId = _publishWithSig({delegatedSigner: profileOwner, signerPrivKey: profileOwnerKey});
|
||||
assertEq(pubId, expectedPubId, 'Wrong pubId');
|
||||
|
||||
assertTrue(_getSigNonce(profileOwner) != nonce, 'Wrong nonce after posting');
|
||||
|
||||
vm.expectRevert(Errors.SignatureInvalid.selector);
|
||||
_publishWithSig({delegatedSigner: profileOwner, signerPrivKey: profileOwnerKey});
|
||||
}
|
||||
|
||||
function testCannotPublishWithSigExpiredDeadline() public {
|
||||
deadline = 10;
|
||||
vm.warp(20);
|
||||
|
||||
vm.expectRevert(Errors.SignatureExpired.selector);
|
||||
_publishWithSig({delegatedSigner: profileOwner, signerPrivKey: otherSignerKey});
|
||||
}
|
||||
|
||||
function testCannotPublishWithSigNotDelegatedExecutor() public {
|
||||
vm.expectRevert(Errors.ExecutorInvalid.selector);
|
||||
_publishWithSig({delegatedSigner: otherSigner, signerPrivKey: otherSignerKey});
|
||||
}
|
||||
|
||||
// positives
|
||||
function testPublish() public {
|
||||
uint256 expectedPubId = _getPubCount(newProfileId) + 1;
|
||||
|
||||
vm.prank(profileOwner);
|
||||
uint256 pubId = _publish();
|
||||
|
||||
assertEq(pubId, expectedPubId);
|
||||
|
||||
Types.Publication memory pub = _getPub(newProfileId, pubId);
|
||||
_verifyPublication(pub, _expectedPubFromInitData());
|
||||
}
|
||||
|
||||
// TODO: Can publish without a collect module
|
||||
// TODO: Can publish without a reference module
|
||||
|
||||
function testPublishWithAWhitelistedReferenceModule() public {
|
||||
mockPostParams.referenceModule = address(mockReferenceModule);
|
||||
mockPostParams.referenceModuleInitData = abi.encode(1);
|
||||
replicateInitData();
|
||||
|
||||
uint256 expectedPubId = _getPubCount(newProfileId) + 1;
|
||||
|
||||
vm.prank(profileOwner);
|
||||
uint256 pubId = _publish();
|
||||
|
||||
assertEq(pubId, expectedPubId);
|
||||
|
||||
Types.Publication memory pub = _getPub(newProfileId, pubId);
|
||||
_verifyPublication(pub, _expectedPubFromInitData());
|
||||
}
|
||||
|
||||
function testPublishWithSig() public {
|
||||
uint256 expectedPubId = _getPubCount(newProfileId) + 1;
|
||||
|
||||
uint256 pubId = _publishWithSig({delegatedSigner: profileOwner, signerPrivKey: profileOwnerKey});
|
||||
assertEq(pubId, expectedPubId);
|
||||
|
||||
Types.Publication memory pub = _getPub(newProfileId, pubId);
|
||||
_verifyPublication(pub, _expectedPubFromInitData());
|
||||
}
|
||||
|
||||
function testDelegatedExecutorPublish() public {
|
||||
_changeDelegatedExecutorsConfig(profileOwner, newProfileId, otherSigner, true);
|
||||
|
||||
uint256 expectedPubId = _getPubCount(newProfileId) + 1;
|
||||
|
||||
vm.prank(otherSigner);
|
||||
uint256 pubId = _publish();
|
||||
assertEq(pubId, expectedPubId);
|
||||
|
||||
Types.Publication memory pub = _getPub(newProfileId, pubId);
|
||||
_verifyPublication(pub, _expectedPubFromInitData());
|
||||
}
|
||||
|
||||
function testDelegatedExecutorPublishWithSig() public {
|
||||
_changeDelegatedExecutorsConfig(profileOwner, newProfileId, otherSigner, true);
|
||||
|
||||
uint256 expectedPubId = _getPubCount(newProfileId) + 1;
|
||||
uint256 pubId = _publishWithSig({delegatedSigner: otherSigner, signerPrivKey: otherSignerKey});
|
||||
assertEq(pubId, expectedPubId);
|
||||
|
||||
Types.Publication memory pub = _getPub(newProfileId, pubId);
|
||||
_verifyPublication(pub, _expectedPubFromInitData());
|
||||
}
|
||||
}
|
||||
|
||||
contract PostTest is PublishingTest {
|
||||
function testPostTest() public {
|
||||
// Prevents being counted in Foundry Coverage
|
||||
}
|
||||
|
||||
function _publish() internal virtual override returns (uint256) {
|
||||
return _post(mockPostParams);
|
||||
}
|
||||
|
||||
function _publishWithSig(
|
||||
address delegatedSigner,
|
||||
uint256 signerPrivKey,
|
||||
uint256 digestDeadline,
|
||||
uint256 sigDeadline
|
||||
) internal virtual override returns (uint256) {
|
||||
bytes32 digest = _getPostTypedDataHash(mockPostParams, nonce, digestDeadline);
|
||||
|
||||
return _postWithSig(mockPostParams, _getSigStruct(delegatedSigner, signerPrivKey, digest, sigDeadline));
|
||||
}
|
||||
|
||||
function _expectedPubFromInitData() internal view virtual override returns (Types.Publication memory) {
|
||||
return _expectedPubFromInitData(mockPostParams);
|
||||
}
|
||||
}
|
||||
|
||||
contract CommentTest is PublishingTest {
|
||||
uint256 postId;
|
||||
|
||||
function replicateInitData() internal override {
|
||||
mockCommentParams.profileId = mockPostParams.profileId;
|
||||
mockCommentParams.contentURI = mockPostParams.contentURI;
|
||||
mockCommentParams.actionModules = mockPostParams.actionModules;
|
||||
mockCommentParams.actionModulesInitDatas = mockPostParams.actionModulesInitDatas;
|
||||
mockCommentParams.referenceModule = mockPostParams.referenceModule;
|
||||
mockCommentParams.referenceModuleInitData = mockPostParams.referenceModuleInitData;
|
||||
}
|
||||
|
||||
function _publish() internal override returns (uint256) {
|
||||
return _comment(mockCommentParams);
|
||||
}
|
||||
|
||||
function _publishWithSig(
|
||||
address delegatedSigner,
|
||||
uint256 signerPrivKey,
|
||||
uint256 digestDeadline,
|
||||
uint256 sigDeadline
|
||||
) internal override returns (uint256) {
|
||||
bytes32 digest = _getCommentTypedDataHash(mockCommentParams, nonce, digestDeadline);
|
||||
|
||||
return _commentWithSig(mockCommentParams, _getSigStruct(delegatedSigner, signerPrivKey, digest, sigDeadline));
|
||||
}
|
||||
|
||||
function _expectedPubFromInitData() internal view override returns (Types.Publication memory) {
|
||||
return _expectedPubFromInitData(mockCommentParams);
|
||||
}
|
||||
|
||||
function setUp() public override {
|
||||
PublishingTest.setUp();
|
||||
|
||||
vm.prank(profileOwner);
|
||||
postId = _post(mockPostParams);
|
||||
}
|
||||
|
||||
// negatives
|
||||
function testCannotCommentOnNonExistentPublication() public {
|
||||
uint256 nonExistentPubId = _getPubCount(newProfileId) + 10;
|
||||
|
||||
replicateInitData();
|
||||
mockCommentParams.pointedPubId = nonExistentPubId;
|
||||
|
||||
vm.prank(profileOwner);
|
||||
vm.expectRevert(Errors.InvalidPointedPub.selector);
|
||||
_publish();
|
||||
}
|
||||
|
||||
function testCannotCommentWithSigOnNonExistentPublication() public {
|
||||
uint256 nonExistentPubId = _getPubCount(newProfileId) + 10;
|
||||
|
||||
replicateInitData();
|
||||
mockCommentParams.pointedPubId = nonExistentPubId;
|
||||
|
||||
vm.expectRevert(Errors.InvalidPointedPub.selector);
|
||||
_publishWithSig({delegatedSigner: profileOwner, signerPrivKey: profileOwnerKey});
|
||||
}
|
||||
|
||||
function testCannotCommentOnTheSamePublicationBeingCreated() public {
|
||||
uint256 nextPubId = _getPubCount(newProfileId) + 1;
|
||||
|
||||
replicateInitData();
|
||||
mockCommentParams.pointedPubId = nextPubId;
|
||||
|
||||
vm.prank(profileOwner);
|
||||
vm.expectRevert(Errors.InvalidPointedPub.selector);
|
||||
_publish();
|
||||
}
|
||||
|
||||
function testCannotCommentWithSigOnTheSamePublicationBeingCreated() public {
|
||||
uint256 nextPubId = _getPubCount(newProfileId) + 1;
|
||||
|
||||
replicateInitData();
|
||||
mockCommentParams.pointedPubId = nextPubId;
|
||||
|
||||
vm.expectRevert(Errors.InvalidPointedPub.selector);
|
||||
_publishWithSig({delegatedSigner: profileOwner, signerPrivKey: profileOwnerKey});
|
||||
}
|
||||
|
||||
function testCannotCommentIfBlocked() public {
|
||||
uint256 commenterProfileId = _createProfile(profileOwner);
|
||||
mockCommentParams.profileId = commenterProfileId;
|
||||
vm.prank(profileOwner);
|
||||
hub.setBlockStatus(mockPostParams.profileId, _toUint256Array(commenterProfileId), _toBoolArray(true));
|
||||
vm.expectRevert(Errors.Blocked.selector);
|
||||
vm.prank(profileOwner);
|
||||
_publish();
|
||||
}
|
||||
|
||||
function testCannotCommentWithSigIfBlocked() public {
|
||||
uint256 commenterProfileId = _createProfile(profileOwner);
|
||||
mockCommentParams.profileId = commenterProfileId;
|
||||
vm.prank(profileOwner);
|
||||
hub.setBlockStatus(mockPostParams.profileId, _toUint256Array(commenterProfileId), _toBoolArray(true));
|
||||
vm.expectRevert(Errors.Blocked.selector);
|
||||
_publishWithSig({delegatedSigner: profileOwner, signerPrivKey: profileOwnerKey});
|
||||
}
|
||||
|
||||
// scenarios
|
||||
function testPostWithReferenceModuleAndComment() public {
|
||||
mockPostParams.referenceModule = address(mockReferenceModule);
|
||||
mockPostParams.referenceModuleInitData = abi.encode(1);
|
||||
vm.prank(profileOwner);
|
||||
postId = _post(mockPostParams);
|
||||
|
||||
mockCommentParams.pointedPubId = postId;
|
||||
vm.prank(profileOwner);
|
||||
uint256 commentPubId = _publish();
|
||||
|
||||
Types.Publication memory pub = _getPub(newProfileId, commentPubId);
|
||||
_verifyPublication(pub, _expectedPubFromInitData());
|
||||
}
|
||||
|
||||
function testCannotCommentOnMirror() public {
|
||||
mockMirrorParams.pointedPubId = postId;
|
||||
vm.prank(profileOwner);
|
||||
uint256 mirrorId = _mirror(mockMirrorParams);
|
||||
|
||||
mockCommentParams.pointedPubId = mirrorId;
|
||||
vm.expectRevert(Errors.InvalidPointedPub.selector);
|
||||
vm.prank(profileOwner);
|
||||
_publish();
|
||||
}
|
||||
|
||||
function testCannotCommentOnMirrorWithSig() public {
|
||||
mockMirrorParams.pointedPubId = postId;
|
||||
vm.prank(profileOwner);
|
||||
uint256 mirrorId = _mirror(mockMirrorParams);
|
||||
|
||||
mockCommentParams.pointedPubId = mirrorId;
|
||||
vm.expectRevert(Errors.InvalidPointedPub.selector);
|
||||
_publishWithSig({delegatedSigner: profileOwner, signerPrivKey: profileOwnerKey});
|
||||
}
|
||||
}
|
||||
|
||||
contract MirrorTest is PublishingTest {
|
||||
uint256 postId;
|
||||
|
||||
function replicateInitData() internal override {
|
||||
mockMirrorParams.profileId = mockPostParams.profileId;
|
||||
}
|
||||
|
||||
function _publish() internal override returns (uint256) {
|
||||
return _mirror(mockMirrorParams);
|
||||
}
|
||||
|
||||
function _publishWithSig(
|
||||
address delegatedSigner,
|
||||
uint256 signerPrivKey,
|
||||
uint256 digestDeadline,
|
||||
uint256 sigDeadline
|
||||
) internal override returns (uint256) {
|
||||
bytes32 digest = _getMirrorTypedDataHash(mockMirrorParams, nonce, digestDeadline);
|
||||
|
||||
return _mirrorWithSig(mockMirrorParams, _getSigStruct(delegatedSigner, signerPrivKey, digest, sigDeadline));
|
||||
}
|
||||
|
||||
function _expectedPubFromInitData() internal view override returns (Types.Publication memory) {
|
||||
return _expectedPubFromInitData(mockMirrorParams);
|
||||
}
|
||||
|
||||
function setUp() public override {
|
||||
PublishingTest.setUp();
|
||||
|
||||
vm.prank(profileOwner);
|
||||
postId = _post(mockPostParams);
|
||||
}
|
||||
|
||||
// ignored - these tests don't apply to mirrors
|
||||
// TODO: Proper tests
|
||||
// function testCannotPublishNotWhitelistedCollectModule() public override {}
|
||||
// function testCannotPublishWithSigNotWhitelistedCollectModule() public override {}
|
||||
|
||||
function testCannotPublishNotWhitelistedReferenceModule() public override {}
|
||||
|
||||
function testCannotPublishWithSigNotWhitelistedReferenceModule() public override {}
|
||||
|
||||
// negatives
|
||||
|
||||
function testCannotMirrorNonExistentPublication() public {
|
||||
uint256 nonExistentPubId = _getPubCount(newProfileId) + 10;
|
||||
|
||||
replicateInitData();
|
||||
mockMirrorParams.pointedPubId = nonExistentPubId;
|
||||
|
||||
vm.prank(profileOwner);
|
||||
vm.expectRevert(Errors.InvalidPointedPub.selector);
|
||||
_publish();
|
||||
}
|
||||
|
||||
function testCannotMirrorWithSigNonExistentPublication() public {
|
||||
uint256 nonExistentPubId = _getPubCount(newProfileId) + 10;
|
||||
|
||||
replicateInitData();
|
||||
mockMirrorParams.pointedPubId = nonExistentPubId;
|
||||
|
||||
vm.expectRevert(Errors.InvalidPointedPub.selector);
|
||||
_publishWithSig({delegatedSigner: profileOwner, signerPrivKey: profileOwnerKey});
|
||||
}
|
||||
|
||||
function testCannotMirrorIfBlocked() public {
|
||||
uint256 mirrorerProfileId = _createProfile(profileOwner);
|
||||
mockMirrorParams.profileId = mirrorerProfileId;
|
||||
vm.prank(profileOwner);
|
||||
hub.setBlockStatus(mockPostParams.profileId, _toUint256Array(mirrorerProfileId), _toBoolArray(true));
|
||||
vm.expectRevert(Errors.Blocked.selector);
|
||||
vm.prank(profileOwner);
|
||||
_publish();
|
||||
}
|
||||
|
||||
function testCannotMirrorWithSigIfBlocked() public {
|
||||
uint256 mirrorerProfileId = _createProfile(profileOwner);
|
||||
mockMirrorParams.profileId = mirrorerProfileId;
|
||||
vm.prank(profileOwner);
|
||||
hub.setBlockStatus(mockPostParams.profileId, _toUint256Array(mirrorerProfileId), _toBoolArray(true));
|
||||
vm.expectRevert(Errors.Blocked.selector);
|
||||
_publishWithSig({delegatedSigner: profileOwner, signerPrivKey: profileOwnerKey});
|
||||
}
|
||||
|
||||
// scenarios
|
||||
function testCannotMirrorAMirror() public {
|
||||
mockMirrorParams.pointedPubId = postId;
|
||||
vm.prank(profileOwner);
|
||||
uint256 firstMirrorId = _publish();
|
||||
|
||||
mockMirrorParams.pointedPubId = firstMirrorId;
|
||||
vm.prank(profileOwner);
|
||||
vm.expectRevert(Errors.InvalidPointedPub.selector);
|
||||
_publish();
|
||||
}
|
||||
|
||||
function testCannotMirrorAMirrorWithSig() public {
|
||||
mockMirrorParams.pointedPubId = postId;
|
||||
vm.prank(profileOwner);
|
||||
uint256 firstMirrorId = _publish();
|
||||
|
||||
mockMirrorParams.pointedPubId = firstMirrorId;
|
||||
vm.expectRevert(Errors.InvalidPointedPub.selector);
|
||||
_publishWithSig({delegatedSigner: profileOwner, signerPrivKey: profileOwnerKey});
|
||||
}
|
||||
}
|
||||
@@ -220,6 +220,34 @@ contract BaseTest is TestSetup {
|
||||
return _calculateDigest(structHash);
|
||||
}
|
||||
|
||||
function _getQuoteTypedDataHash(
|
||||
Types.QuoteParams memory quoteParams,
|
||||
uint256 nonce,
|
||||
uint256 deadline
|
||||
) internal view returns (bytes32) {
|
||||
bytes32 structHash = keccak256(
|
||||
_abiEncode(
|
||||
ReferenceParamsForAbiEncode(
|
||||
Typehash.QUOTE,
|
||||
quoteParams.profileId,
|
||||
keccak256(bytes(quoteParams.contentURI)),
|
||||
quoteParams.pointedProfileId,
|
||||
quoteParams.pointedPubId,
|
||||
quoteParams.referrerProfileIds,
|
||||
quoteParams.referrerPubIds,
|
||||
keccak256(quoteParams.referenceModuleData),
|
||||
quoteParams.actionModules,
|
||||
_hashActionModulesInitDatas(quoteParams.actionModulesInitDatas),
|
||||
quoteParams.referenceModule,
|
||||
keccak256(quoteParams.referenceModuleInitData),
|
||||
nonce,
|
||||
deadline
|
||||
)
|
||||
)
|
||||
);
|
||||
return _calculateDigest(structHash);
|
||||
}
|
||||
|
||||
function _getMirrorTypedDataHash(
|
||||
uint256 profileId,
|
||||
uint256 pointedProfileId,
|
||||
|
||||
@@ -32,6 +32,7 @@ contract TestSetup is Test, ForkManagement, ArrayHelpers {
|
||||
}
|
||||
|
||||
uint256 newProfileId; // TODO: We should get rid of this everywhere, and create dedicated profiles instead (see Follow tests)
|
||||
uint256 mockPostId;
|
||||
|
||||
address deployer;
|
||||
address governance;
|
||||
@@ -66,6 +67,7 @@ contract TestSetup is Test, ForkManagement, ArrayHelpers {
|
||||
|
||||
Types.PostParams mockPostParams;
|
||||
Types.CommentParams mockCommentParams;
|
||||
Types.QuoteParams mockQuoteParams;
|
||||
Types.MirrorParams mockMirrorParams;
|
||||
Types.CollectParams mockCollectParams;
|
||||
Types.PublicationActionParams mockActParams;
|
||||
@@ -111,9 +113,6 @@ contract TestSetup is Test, ForkManagement, ArrayHelpers {
|
||||
hubAsProxy = TransparentUpgradeableProxy(payable(address(hub)));
|
||||
moduleGlobals = ModuleGlobals(json.readAddress(string(abi.encodePacked('.', targetEnv, '.ModuleGlobals'))));
|
||||
|
||||
newProfileId = _getNextProfileId();
|
||||
console.log('newProfileId:', newProfileId);
|
||||
|
||||
deployer = address(1);
|
||||
|
||||
governance = hub.getGovernance();
|
||||
@@ -123,7 +122,6 @@ contract TestSetup is Test, ForkManagement, ArrayHelpers {
|
||||
}
|
||||
|
||||
function deployBaseContracts() internal {
|
||||
newProfileId = FIRST_PROFILE_ID;
|
||||
deployer = address(1);
|
||||
governance = address(2);
|
||||
treasury = address(3);
|
||||
@@ -208,6 +206,8 @@ contract TestSetup is Test, ForkManagement, ArrayHelpers {
|
||||
followNFTURI: MOCK_URI
|
||||
});
|
||||
|
||||
newProfileId = hub.createProfile(mockCreateProfileParams);
|
||||
|
||||
// Precompute basic post data.
|
||||
mockPostParams = Types.PostParams({
|
||||
profileId: newProfileId,
|
||||
@@ -218,12 +218,30 @@ contract TestSetup is Test, ForkManagement, ArrayHelpers {
|
||||
referenceModuleInitData: ''
|
||||
});
|
||||
|
||||
vm.prank(profileOwner);
|
||||
mockPostId = hub.post(mockPostParams);
|
||||
|
||||
// Precompute basic comment data.
|
||||
mockCommentParams = Types.CommentParams({
|
||||
profileId: newProfileId,
|
||||
contentURI: MOCK_URI,
|
||||
pointedProfileId: newProfileId,
|
||||
pointedPubId: FIRST_PUB_ID,
|
||||
pointedPubId: mockPostId,
|
||||
referrerProfileIds: _emptyUint256Array(),
|
||||
referrerPubIds: _emptyUint256Array(),
|
||||
referenceModuleData: '',
|
||||
actionModules: _toAddressArray(address(mockActionModule)),
|
||||
actionModulesInitDatas: _toBytesArray(abi.encode(1)),
|
||||
referenceModule: address(0),
|
||||
referenceModuleInitData: ''
|
||||
});
|
||||
|
||||
// Precompute basic quote data.
|
||||
mockQuoteParams = Types.QuoteParams({
|
||||
profileId: newProfileId,
|
||||
contentURI: MOCK_URI,
|
||||
pointedProfileId: newProfileId,
|
||||
pointedPubId: mockPostId,
|
||||
referrerProfileIds: _emptyUint256Array(),
|
||||
referrerPubIds: _emptyUint256Array(),
|
||||
referenceModuleData: '',
|
||||
@@ -237,7 +255,7 @@ contract TestSetup is Test, ForkManagement, ArrayHelpers {
|
||||
mockMirrorParams = Types.MirrorParams({
|
||||
profileId: newProfileId,
|
||||
pointedProfileId: newProfileId,
|
||||
pointedPubId: FIRST_PUB_ID,
|
||||
pointedPubId: mockPostId,
|
||||
referrerProfileIds: _emptyUint256Array(),
|
||||
referrerPubIds: _emptyUint256Array(),
|
||||
referenceModuleData: ''
|
||||
@@ -252,18 +270,6 @@ contract TestSetup is Test, ForkManagement, ArrayHelpers {
|
||||
actionModuleAddress: address(mockActionModule),
|
||||
actionModuleData: abi.encode(true)
|
||||
});
|
||||
|
||||
// // Precompute basic collect data.
|
||||
// mockCollectParams = Types.CollectParams({
|
||||
// publicationCollectedProfileId: newProfileId,
|
||||
// publicationCollectedId: FIRST_PUB_ID,
|
||||
// collectorProfileId: newProfileId,
|
||||
// referrerProfileIds: _emptyUint256Array(),
|
||||
// referrerPubIds: _emptyUint256Array(),
|
||||
// collectModuleData: ''
|
||||
// });
|
||||
|
||||
hub.createProfile(mockCreateProfileParams);
|
||||
}
|
||||
|
||||
// TODO: Find a better place for such helpers that have access to Hub without rekting inheritance
|
||||
|
||||
@@ -13,16 +13,6 @@ contract ArrayHelpers {
|
||||
return ret;
|
||||
}
|
||||
|
||||
function _emptyAddressArray() internal pure returns (address[] memory) {
|
||||
address[] memory ret = new address[](0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
function _emptyBytesArray() internal pure returns (bytes[] memory) {
|
||||
bytes[] memory ret = new bytes[](0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
function _emptyPubTypesArray() internal pure returns (Types.PublicationType[] memory) {
|
||||
Types.PublicationType[] memory ret = new Types.PublicationType[](0);
|
||||
return ret;
|
||||
|
||||
76
test/foundry/publications/CommentTest.t.sol
Normal file
76
test/foundry/publications/CommentTest.t.sol
Normal file
@@ -0,0 +1,76 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.13;
|
||||
|
||||
import {Types} from 'contracts/libraries/constants/Types.sol';
|
||||
import {PublicationTest} from 'test/foundry/publications/PublicationTest.t.sol';
|
||||
import {MetaTxNegatives} from 'test/foundry/MetaTxNegatives.t.sol';
|
||||
|
||||
contract CommentTest is PublicationTest {
|
||||
function testCommentTest() public {
|
||||
// Prevents being counted in Foundry Coverage
|
||||
}
|
||||
|
||||
function setUp() public virtual override {
|
||||
super.setUp();
|
||||
mockCommentParams.profileId = publisherProfileId;
|
||||
}
|
||||
|
||||
function _publish(uint256 signerPk, uint256 publisherProfileId) internal virtual override returns (uint256) {
|
||||
mockCommentParams.profileId = publisherProfileId;
|
||||
vm.prank(vm.addr(signerPk));
|
||||
return hub.comment(mockCommentParams);
|
||||
}
|
||||
|
||||
function _pubType() internal virtual override returns (Types.PublicationType) {
|
||||
return Types.PublicationType.Comment;
|
||||
}
|
||||
}
|
||||
|
||||
contract CommentMetaTxTest is CommentTest, MetaTxNegatives {
|
||||
mapping(address => uint256) cachedNonceByAddress;
|
||||
|
||||
function testCommentMetaTxTest() public {
|
||||
// Prevents being counted in Foundry Coverage
|
||||
}
|
||||
|
||||
function setUp() public virtual override(CommentTest, MetaTxNegatives) {
|
||||
CommentTest.setUp();
|
||||
MetaTxNegatives.setUp();
|
||||
cachedNonceByAddress[profileOwner] = _getSigNonce(profileOwner);
|
||||
}
|
||||
|
||||
function _publish(uint256 signerPk, uint256 publisherProfileId) internal virtual override returns (uint256) {
|
||||
mockCommentParams.profileId = publisherProfileId;
|
||||
address signer = vm.addr(signerPk);
|
||||
return
|
||||
hub.commentWithSig(
|
||||
mockCommentParams,
|
||||
_getSigStruct({
|
||||
signer: signer,
|
||||
pKey: signerPk,
|
||||
digest: _getCommentTypedDataHash({
|
||||
commentParams: mockCommentParams,
|
||||
nonce: cachedNonceByAddress[signer],
|
||||
deadline: type(uint256).max
|
||||
}),
|
||||
deadline: type(uint256).max
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
function _executeMetaTx(uint256 signerPk, uint256 nonce, uint256 deadline) internal virtual override {
|
||||
hub.commentWithSig(
|
||||
mockCommentParams,
|
||||
_getSigStruct({
|
||||
signer: vm.addr(_getDefaultMetaTxSignerPk()),
|
||||
pKey: signerPk,
|
||||
digest: _getCommentTypedDataHash(mockCommentParams, nonce, deadline),
|
||||
deadline: deadline
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
function _getDefaultMetaTxSignerPk() internal virtual override returns (uint256) {
|
||||
return publisherOwnerPk;
|
||||
}
|
||||
}
|
||||
76
test/foundry/publications/MirrorTest.t.sol
Normal file
76
test/foundry/publications/MirrorTest.t.sol
Normal file
@@ -0,0 +1,76 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.13;
|
||||
|
||||
import {Types} from 'contracts/libraries/constants/Types.sol';
|
||||
import {PublicationTest} from 'test/foundry/publications/PublicationTest.t.sol';
|
||||
import {MetaTxNegatives} from 'test/foundry/MetaTxNegatives.t.sol';
|
||||
|
||||
contract MirrorTest is PublicationTest {
|
||||
function testMirrorTest() public {
|
||||
// Prevents being counted in Foundry Coverage
|
||||
}
|
||||
|
||||
function setUp() public virtual override {
|
||||
super.setUp();
|
||||
mockMirrorParams.profileId = publisherProfileId;
|
||||
}
|
||||
|
||||
function _publish(uint256 signerPk, uint256 publisherProfileId) internal virtual override returns (uint256) {
|
||||
mockMirrorParams.profileId = publisherProfileId;
|
||||
vm.prank(vm.addr(signerPk));
|
||||
return hub.mirror(mockMirrorParams);
|
||||
}
|
||||
|
||||
function _pubType() internal virtual override returns (Types.PublicationType) {
|
||||
return Types.PublicationType.Mirror;
|
||||
}
|
||||
}
|
||||
|
||||
contract MirrorMetaTxTest is MirrorTest, MetaTxNegatives {
|
||||
mapping(address => uint256) cachedNonceByAddress;
|
||||
|
||||
function testMirrorMetaTxTest() public {
|
||||
// Prevents being counted in Foundry Coverage
|
||||
}
|
||||
|
||||
function setUp() public virtual override(MirrorTest, MetaTxNegatives) {
|
||||
MirrorTest.setUp();
|
||||
MetaTxNegatives.setUp();
|
||||
cachedNonceByAddress[profileOwner] = _getSigNonce(profileOwner);
|
||||
}
|
||||
|
||||
function _publish(uint256 signerPk, uint256 publisherProfileId) internal virtual override returns (uint256) {
|
||||
mockMirrorParams.profileId = publisherProfileId;
|
||||
address signer = vm.addr(signerPk);
|
||||
return
|
||||
hub.mirrorWithSig(
|
||||
mockMirrorParams,
|
||||
_getSigStruct({
|
||||
signer: signer,
|
||||
pKey: signerPk,
|
||||
digest: _getMirrorTypedDataHash({
|
||||
mirrorParams: mockMirrorParams,
|
||||
nonce: cachedNonceByAddress[signer],
|
||||
deadline: type(uint256).max
|
||||
}),
|
||||
deadline: type(uint256).max
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
function _executeMetaTx(uint256 signerPk, uint256 nonce, uint256 deadline) internal virtual override {
|
||||
hub.mirrorWithSig(
|
||||
mockMirrorParams,
|
||||
_getSigStruct({
|
||||
signer: vm.addr(_getDefaultMetaTxSignerPk()),
|
||||
pKey: signerPk,
|
||||
digest: _getMirrorTypedDataHash(mockMirrorParams, nonce, deadline),
|
||||
deadline: deadline
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
function _getDefaultMetaTxSignerPk() internal virtual override returns (uint256) {
|
||||
return publisherOwnerPk;
|
||||
}
|
||||
}
|
||||
76
test/foundry/publications/PostTest.t.sol
Normal file
76
test/foundry/publications/PostTest.t.sol
Normal file
@@ -0,0 +1,76 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.13;
|
||||
|
||||
import {Types} from 'contracts/libraries/constants/Types.sol';
|
||||
import {PublicationTest} from 'test/foundry/publications/PublicationTest.t.sol';
|
||||
import {MetaTxNegatives} from 'test/foundry/MetaTxNegatives.t.sol';
|
||||
|
||||
contract PostTest is PublicationTest {
|
||||
function testPostTest() public {
|
||||
// Prevents being counted in Foundry Coverage
|
||||
}
|
||||
|
||||
function setUp() public virtual override {
|
||||
super.setUp();
|
||||
mockPostParams.profileId = publisherProfileId;
|
||||
}
|
||||
|
||||
function _publish(uint256 signerPk, uint256 publisherProfileId) internal virtual override returns (uint256) {
|
||||
mockPostParams.profileId = publisherProfileId;
|
||||
vm.prank(vm.addr(signerPk));
|
||||
return hub.post(mockPostParams);
|
||||
}
|
||||
|
||||
function _pubType() internal virtual override returns (Types.PublicationType) {
|
||||
return Types.PublicationType.Post;
|
||||
}
|
||||
}
|
||||
|
||||
contract PostMetaTxTest is PostTest, MetaTxNegatives {
|
||||
mapping(address => uint256) cachedNonceByAddress;
|
||||
|
||||
function testPostMetaTxTest() public {
|
||||
// Prevents being counted in Foundry Coverage
|
||||
}
|
||||
|
||||
function setUp() public virtual override(PostTest, MetaTxNegatives) {
|
||||
PostTest.setUp();
|
||||
MetaTxNegatives.setUp();
|
||||
cachedNonceByAddress[profileOwner] = _getSigNonce(profileOwner);
|
||||
}
|
||||
|
||||
function _publish(uint256 signerPk, uint256 publisherProfileId) internal virtual override returns (uint256) {
|
||||
mockPostParams.profileId = publisherProfileId;
|
||||
address signer = vm.addr(signerPk);
|
||||
return
|
||||
hub.postWithSig(
|
||||
mockPostParams,
|
||||
_getSigStruct({
|
||||
signer: signer,
|
||||
pKey: signerPk,
|
||||
digest: _getPostTypedDataHash({
|
||||
postParams: mockPostParams,
|
||||
nonce: cachedNonceByAddress[signer],
|
||||
deadline: type(uint256).max
|
||||
}),
|
||||
deadline: type(uint256).max
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
function _executeMetaTx(uint256 signerPk, uint256 nonce, uint256 deadline) internal virtual override {
|
||||
hub.postWithSig(
|
||||
mockPostParams,
|
||||
_getSigStruct({
|
||||
signer: vm.addr(_getDefaultMetaTxSignerPk()),
|
||||
pKey: signerPk,
|
||||
digest: _getPostTypedDataHash(mockPostParams, nonce, deadline),
|
||||
deadline: deadline
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
function _getDefaultMetaTxSignerPk() internal virtual override returns (uint256) {
|
||||
return publisherOwnerPk;
|
||||
}
|
||||
}
|
||||
108
test/foundry/publications/PublicationTest.t.sol
Normal file
108
test/foundry/publications/PublicationTest.t.sol
Normal file
@@ -0,0 +1,108 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.13;
|
||||
|
||||
import 'test/foundry/base/BaseTest.t.sol';
|
||||
|
||||
/**
|
||||
* Tests shared among all type of publications. Posts, Comments, Quotes, and Mirrors.
|
||||
*/
|
||||
abstract contract PublicationTest is BaseTest {
|
||||
uint256 publisherOwnerPk;
|
||||
address publisherOwner;
|
||||
uint256 publisherProfileId;
|
||||
|
||||
function _publish(uint256 signerPk, uint256 publisherProfileId) internal virtual returns (uint256);
|
||||
|
||||
function _pubType() internal virtual returns (Types.PublicationType);
|
||||
|
||||
function setUp() public virtual override {
|
||||
super.setUp();
|
||||
(publisherOwnerPk, publisherOwner, publisherProfileId) = _loadAccountAs('Publisher');
|
||||
}
|
||||
|
||||
// Negatives
|
||||
|
||||
function testCannotPublish_IfProtocolStateIs_Paused() public {
|
||||
vm.prank(governance);
|
||||
hub.setState(Types.ProtocolState.Paused);
|
||||
|
||||
vm.expectRevert(Errors.PublishingPaused.selector);
|
||||
_publish({signerPk: publisherOwnerPk, publisherProfileId: publisherProfileId});
|
||||
}
|
||||
|
||||
function testCannotPublish_IfProtocolStateIs_PublishingPaused() public {
|
||||
vm.prank(governance);
|
||||
hub.setState(Types.ProtocolState.PublishingPaused);
|
||||
|
||||
vm.expectRevert(Errors.PublishingPaused.selector);
|
||||
_publish({signerPk: publisherOwnerPk, publisherProfileId: publisherProfileId});
|
||||
}
|
||||
|
||||
function testCannotPublish_IfExecutorIsNot_PublisherProfileOwnerOrDelegatedExecutor(
|
||||
uint256 nonOwnerNorDelegatedExecutorPk
|
||||
) public {
|
||||
nonOwnerNorDelegatedExecutorPk = _boundPk(nonOwnerNorDelegatedExecutorPk);
|
||||
vm.assume(nonOwnerNorDelegatedExecutorPk != publisherOwnerPk);
|
||||
address nonOwnerNorDelegatedExecutor = vm.addr(nonOwnerNorDelegatedExecutorPk);
|
||||
vm.assume(!hub.isDelegatedExecutorApproved(publisherProfileId, nonOwnerNorDelegatedExecutor));
|
||||
|
||||
vm.expectRevert(Errors.ExecutorInvalid.selector);
|
||||
_publish({signerPk: nonOwnerNorDelegatedExecutorPk, publisherProfileId: publisherProfileId});
|
||||
}
|
||||
|
||||
// Scenarios
|
||||
|
||||
function testPublisherPubCountIs_IncrementedByOne_AfterPublishing() public {
|
||||
uint256 pubCountBeforePublishing = hub.getPubCount(publisherProfileId);
|
||||
_publish({signerPk: publisherOwnerPk, publisherProfileId: publisherProfileId});
|
||||
uint256 pubCountAfterPublishing = hub.getPubCount(publisherProfileId);
|
||||
assertEq(pubCountAfterPublishing, pubCountBeforePublishing + 1);
|
||||
}
|
||||
|
||||
function testPubIdAssignedIs_EqualsToPubCount_AfterPublishing() public {
|
||||
uint256 pubIdAssigned = _publish({signerPk: publisherOwnerPk, publisherProfileId: publisherProfileId});
|
||||
uint256 pubCountAfterPublishing = hub.getPubCount(publisherProfileId);
|
||||
assertEq(pubIdAssigned, pubCountAfterPublishing);
|
||||
}
|
||||
|
||||
function testCanPublishIf_ExecutorIs_PublisherProfileApprovedDelegatedExecutor(uint256 delegatedExecutorPk) public {
|
||||
delegatedExecutorPk = _boundPk(delegatedExecutorPk);
|
||||
vm.assume(delegatedExecutorPk != publisherOwnerPk);
|
||||
address delegatedExecutor = vm.addr(delegatedExecutorPk);
|
||||
vm.prank(publisherOwner);
|
||||
hub.changeDelegatedExecutorsConfig({
|
||||
delegatorProfileId: publisherProfileId,
|
||||
delegatedExecutors: _toAddressArray(delegatedExecutor),
|
||||
approvals: _toBoolArray(true)
|
||||
});
|
||||
|
||||
_publish({signerPk: delegatedExecutorPk, publisherProfileId: publisherProfileId});
|
||||
}
|
||||
|
||||
function testCanPublishIf_ExecutorIs_PublisherProfileOwner() public {
|
||||
_publish({signerPk: publisherOwnerPk, publisherProfileId: publisherProfileId});
|
||||
}
|
||||
|
||||
function testPublicationTypeIsCorrect() public {
|
||||
uint256 publicationIdAssigned = _publish({signerPk: publisherOwnerPk, publisherProfileId: publisherProfileId});
|
||||
Types.PublicationType assignedPubType = hub.getPublicationType(publisherProfileId, publicationIdAssigned);
|
||||
Types.PublicationType expectedPubType = _pubType();
|
||||
assertTrue(assignedPubType == expectedPubType, 'Assigned publication type is different than the expected one');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for publications that can handle actions. Posts, Comments, and Quotes, but not Mirrors.
|
||||
*/
|
||||
abstract contract ActionablePublicationTest is PublicationTest {
|
||||
function _setActionModules(address[] memory actionModules, bytes[] memory actionModulesInitDatas) internal virtual;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for publications that points to another publication. Comments, Quotes, and Mirrors, but not Posts.
|
||||
*/
|
||||
abstract contract ReferencePublicationTest is PublicationTest {
|
||||
function _setReferrers(uint256[] memory referrerProfileIds, uint256[] memory referrerPubIds) internal virtual;
|
||||
|
||||
function _setReferenceModuleData(bytes memory referenceModuleData) internal virtual;
|
||||
}
|
||||
76
test/foundry/publications/QuoteTest.t.sol
Normal file
76
test/foundry/publications/QuoteTest.t.sol
Normal file
@@ -0,0 +1,76 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.13;
|
||||
|
||||
import {Types} from 'contracts/libraries/constants/Types.sol';
|
||||
import {PublicationTest} from 'test/foundry/publications/PublicationTest.t.sol';
|
||||
import {MetaTxNegatives} from 'test/foundry/MetaTxNegatives.t.sol';
|
||||
|
||||
contract QuoteTest is PublicationTest {
|
||||
function testQuoteTest() public {
|
||||
// Prevents being counted in Foundry Coverage
|
||||
}
|
||||
|
||||
function setUp() public virtual override {
|
||||
super.setUp();
|
||||
mockQuoteParams.profileId = publisherProfileId;
|
||||
}
|
||||
|
||||
function _publish(uint256 signerPk, uint256 publisherProfileId) internal virtual override returns (uint256) {
|
||||
mockQuoteParams.profileId = publisherProfileId;
|
||||
vm.prank(vm.addr(signerPk));
|
||||
return hub.quote(mockQuoteParams);
|
||||
}
|
||||
|
||||
function _pubType() internal virtual override returns (Types.PublicationType) {
|
||||
return Types.PublicationType.Quote;
|
||||
}
|
||||
}
|
||||
|
||||
contract QuoteMetaTxTest is QuoteTest, MetaTxNegatives {
|
||||
mapping(address => uint256) cachedNonceByAddress;
|
||||
|
||||
function testQuoteMetaTxTest() public {
|
||||
// Prevents being counted in Foundry Coverage
|
||||
}
|
||||
|
||||
function setUp() public virtual override(QuoteTest, MetaTxNegatives) {
|
||||
QuoteTest.setUp();
|
||||
MetaTxNegatives.setUp();
|
||||
cachedNonceByAddress[profileOwner] = _getSigNonce(profileOwner);
|
||||
}
|
||||
|
||||
function _publish(uint256 signerPk, uint256 publisherProfileId) internal virtual override returns (uint256) {
|
||||
mockQuoteParams.profileId = publisherProfileId;
|
||||
address signer = vm.addr(signerPk);
|
||||
return
|
||||
hub.quoteWithSig(
|
||||
mockQuoteParams,
|
||||
_getSigStruct({
|
||||
signer: signer,
|
||||
pKey: signerPk,
|
||||
digest: _getQuoteTypedDataHash({
|
||||
quoteParams: mockQuoteParams,
|
||||
nonce: cachedNonceByAddress[signer],
|
||||
deadline: type(uint256).max
|
||||
}),
|
||||
deadline: type(uint256).max
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
function _executeMetaTx(uint256 signerPk, uint256 nonce, uint256 deadline) internal virtual override {
|
||||
hub.quoteWithSig(
|
||||
mockQuoteParams,
|
||||
_getSigStruct({
|
||||
signer: vm.addr(_getDefaultMetaTxSignerPk()),
|
||||
pKey: signerPk,
|
||||
digest: _getQuoteTypedDataHash(mockQuoteParams, nonce, deadline),
|
||||
deadline: deadline
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
function _getDefaultMetaTxSignerPk() internal virtual override returns (uint256) {
|
||||
return publisherOwnerPk;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user