Files
core/test/ReferralSystem.t.sol
vicnaum be4c309326 test: referrals
Co-authored-by: Alan <donosonaumczuk@gmail.com>
2023-06-20 19:37:10 +02:00

394 lines
16 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import 'test/mocks/MockModule.sol';
import 'test/base/BaseTest.t.sol';
/**
* Tests shared among all operations where the Lens V2 Referral System applies, e.g. act, quote, comment, mirror.
*/
contract ReferralSystemTest is BaseTest {
TestAccount[] testAccounts;
// function _setReferrers(uint256[] memory referrerProfileIds, uint256[] memory referrerPubIds) internal virtual;
function _executeOperation(TestPublication memory target, TestPublication memory referralPub) internal virtual {
uint256 testAccountId = testAccounts.length;
TestAccount memory actor = _loadAccountAs(string.concat('TESTACCOUNT_', vm.toString(testAccountId)));
testAccounts.push(actor);
Types.PublicationActionParams memory actParams = _getDefaultPublicationActionParams();
actParams.publicationActedProfileId = target.profileId;
actParams.publicationActedId = target.pubId;
actParams.actorProfileId = actor.profileId;
actParams.referrerProfileIds = _toUint256Array(referralPub.profileId);
actParams.referrerPubIds = _toUint256Array(referralPub.pubId);
console.log('ACTING on %s, %s', vm.toString(target.profileId), vm.toString(target.pubId));
console.log(' with referral: %s, %s', vm.toString(referralPub.profileId), vm.toString(referralPub.pubId));
// TODO:
// we do some action on target while passing reference as referral and expect it to be called,
// so expectCall should check that the reference was passed as referral and it didn't revert.
// vm.expectCall /* */();
// TODO:
// _executeOperation(target, referralPub);
vm.prank(actor.owner);
hub.act(actParams);
}
function setUp() public virtual override {
super.setUp();
}
struct Tree {
TestPublication post;
TestPublication[] references;
TestPublication[] mirrors;
}
// All references are V2 now
function testV2References() public virtual {
// for (uint256 commentQuoteFuzzBitmap = 0; commentQuoteFuzzBitmap < 32; commentQuoteFuzzBitmap++) {
// Tree memory treeV2 = _createV2Tree(commentQuoteFuzzBitmap);
// }
Tree memory treeV2 = _createV2Tree(14);
{
// Target a post with quote/comment as referrals
TestPublication memory target = treeV2.post;
for (uint256 i = 0; i < treeV2.references.length; i++) {
TestPublication memory referralPub = treeV2.references[i];
_executeOperation(target, referralPub);
}
}
{
// Target a post with mirrors as referrals
TestPublication memory target = treeV2.post;
for (uint256 i = 0; i < treeV2.mirrors.length; i++) {
TestPublication memory referralPub = treeV2.mirrors[i];
_executeOperation(target, referralPub);
}
}
{
// Target as a quote/comment node and pass another quote/comments as referral
for (uint256 i = 0; i < treeV2.references.length; i++) {
TestPublication memory target = treeV2.references[i];
for (uint256 j = 0; j < treeV2.references.length; j++) {
TestPublication memory referralPub = treeV2.references[j];
if (i == j) continue; // skip self
// vm.expectCall /* */();
_executeOperation(target, referralPub);
}
// // One special case is a post as referal for reference node
// TestPublication memory referralPub = treeV2.post;
// // vm.expectCall /* */();
// _executeOperation(target, referralPub);
}
}
// {
// // Target as a mirror node
// // A mirror cannot be a target - so we expect revert here
// for (uint256 i = 0; i < treeV2.mirrors.length; i++) {
// uint256 target = treeV2.mirrors[i];
// for (uint256 j = 0; i < treeV2.references.length; j++) {
// uint256 referencePub = treeV2.references[j];
// // vm.expectRevert /* */();
// _executeOperation(target, referencePub);
// }
// // One special case is a post as referal for mirror node
// uint256 referencePub = treeV2.post;
// // vm.expectRevert /* */();
// _executeOperation(target, referencePub);
// }
// }
}
function _createV2Tree(uint256 commentQuoteFuzzBitmap) internal returns (Tree memory) {
/*
Post_1
|
|-- Comment/Quote_0 -- Mirror_0 (mirror of a direct reference)
| |
| |-- Comment/Quote_1 -- Mirror_1 (mirror of a 1st level reference)
| |
| |-- Comment/Quote_2 -- Mirror_2 (mirror of a 2nd level reference)
| |
| |-- Comment/Quote_3 -- Mirror_3 (mirror of a 3rd level reference)
|
|
|-- Comment/Quote_4 -- Mirror_4 (a different branch)
|
|
|-- Mirror_5 (direct post mirror)
*/
// Created POST: 2, 1
// Created COMMENT: (2, 1) <= (3, 1)
// Created MIRROR: (3, 1) <= (4, 1)
// Created QUOTE: (3, 1) <= (5, 1)
// Created MIRROR: (5, 1) <= (6, 1)
// Created QUOTE: (5, 1) <= (7, 1)
// Created MIRROR: (7, 1) <= (8, 1)
// Created QUOTE: (7, 1) <= (9, 1)
// Created MIRROR: (9, 1) <= (10, 1)
// Created COMMENT: (2, 1) <= (11, 1)
// Created MIRROR: (11, 1) <= (12, 1)
// Created MIRROR: (2, 1) <= (13, 1)
// ACTING on 2, 1
// with referral: 3, 1
// ACTING on 2, 1
// with referral: 5, 1
// ACTING on 2, 1
// with referral: 7, 1
// ACTING on 2, 1
// with referral: 9, 1
// ACTING on 2, 1
// with referral: 11, 1
// ACTING on 2, 1
// with referral: 4, 1
// ACTING on 2, 1
// with referral: 6, 1
// ACTING on 2, 1
// with referral: 8, 1
// ACTING on 2, 1
// with referral: 10, 1
// ACTING on 2, 1
// with referral: 12, 1
// ACTING on 2, 1
// with referral: 13, 1
// ACTING on 3, 1
// with referral: 5, 1
// ACTING on 3, 1
// with referral: 7, 1
// ACTING on 3, 1
// with referral: 9, 1
// ACTING on 3, 1
// with referral: 11, 1
Tree memory tree;
tree.references = new TestPublication[](5);
tree.mirrors = new TestPublication[](6);
tree.post = post();
tree.references[0] = _commentOrQuote(tree.post, commentQuoteFuzzBitmap, 0);
tree.mirrors[0] = mirror(tree.references[0]);
tree.references[1] = _commentOrQuote(tree.references[0], commentQuoteFuzzBitmap, 1);
tree.mirrors[1] = mirror(tree.references[1]);
tree.references[2] = _commentOrQuote(tree.references[1], commentQuoteFuzzBitmap, 2);
tree.mirrors[2] = mirror(tree.references[2]);
tree.references[3] = _commentOrQuote(tree.references[2], commentQuoteFuzzBitmap, 3);
tree.mirrors[3] = mirror(tree.references[3]);
tree.references[4] = _commentOrQuote(tree.post, commentQuoteFuzzBitmap, 4);
tree.mirrors[4] = mirror(tree.references[4]);
tree.mirrors[5] = mirror(tree.post);
return tree;
}
// function _createV1ContaminatedTree(uint256 commentQuoteFuzzBitmap) internal returns (Tree memory) {
// /*
// Post_1 (V1)
// |
// |-- Comment/Quote_0 -- Mirror_0 (mirror of a direct reference)
// | |
// | |-- Comment/Quote_1 -- Mirror_1 (mirror of a 1st level reference)
// | |
// | |-- Comment/Quote_2 -- Mirror_2 (mirror of a 2nd level reference)
// | |
// | |-- Comment/Quote_3 -- Mirror_3 (mirror of a 3rd level reference)
// |
// |
// |-- Comment/Quote_4 -- Mirror_4 (a different branch)
// |
// |
// |-- Mirror_5 (direct post mirror)
// */
// Tree memory tree;
// tree.references = new uint256[](5);
// tree.mirrors = new uint256[](6);
// tree.post = post();
// _toV1Post(tree.post);
// tree.references[0] = _commentOrQuote(tree.post, commentQuoteFuzzBitmap, 0);
// tree.mirrors[0] = mirror(tree.references[0]);
// tree.references[1] = _commentOrQuote(tree.references[0], commentQuoteFuzzBitmap, 1);
// tree.mirrors[1] = mirror(tree.references[1]);
// tree.references[2] = _commentOrQuote(tree.references[1], commentQuoteFuzzBitmap, 2);
// tree.mirrors[2] = mirror(tree.references[2]);
// tree.references[3] = _commentOrQuote(tree.references[2], commentQuoteFuzzBitmap, 3);
// tree.mirrors[3] = mirror(tree.references[3]);
// tree.references[4] = _commentOrQuote(tree.post, commentQuoteFuzzBitmap, 4);
// tree.mirrors[4] = mirror(tree.references[4]);
// tree.mirrors[5] = mirror(tree.post);
// return tree;
// }
function _commentOrQuote(
TestPublication memory testPub,
uint256 commentQuoteFuzzBitmap,
uint256 commentQuoteIndex
) internal returns (TestPublication memory) {
uint256 commentQuoteFuzz = (commentQuoteFuzzBitmap >> (commentQuoteIndex)) & 1;
if (commentQuoteFuzz == 0) {
return comment(testPub);
} else {
return quote(testPub);
}
}
function _toV1Post(TestPublication memory testPub) internal {
// TODO
}
function post() internal returns (TestPublication memory) {
uint256 testAccountId = testAccounts.length;
TestAccount memory publisher = _loadAccountAs(string.concat('TESTACCOUNT_', vm.toString(testAccountId)));
testAccounts.push(publisher);
Types.PostParams memory postParams = _getDefaultPostParams();
postParams.profileId = publisher.profileId;
vm.prank(publisher.owner);
uint256 pubId = hub.post(postParams);
console.log('Created POST: %s, %s', publisher.profileId, pubId);
return TestPublication(publisher.profileId, pubId);
}
function mirror(TestPublication memory testPub) internal returns (TestPublication memory) {
uint256 testAccountId = testAccounts.length;
TestAccount memory publisher = _loadAccountAs(string.concat('TESTACCOUNT_', vm.toString(testAccountId)));
testAccounts.push(publisher);
Types.MirrorParams memory mirrorParams = _getDefaultMirrorParams();
mirrorParams.profileId = publisher.profileId;
mirrorParams.pointedPubId = testPub.pubId;
mirrorParams.pointedProfileId = testPub.profileId;
vm.prank(publisher.owner);
uint256 pubId = hub.mirror(mirrorParams);
console.log(
'Created MIRROR: (%s) <= (%s)',
string.concat(vm.toString(testPub.profileId), ', ', vm.toString(testPub.pubId)),
string.concat(vm.toString(publisher.profileId), ', ', vm.toString(pubId))
);
return TestPublication(publisher.profileId, pubId);
}
function comment(TestPublication memory testPub) internal returns (TestPublication memory) {
uint256 testAccountId = testAccounts.length;
TestAccount memory publisher = _loadAccountAs(string.concat('TESTACCOUNT_', vm.toString(testAccountId)));
testAccounts.push(publisher);
Types.CommentParams memory commentParams = _getDefaultCommentParams();
commentParams.profileId = publisher.profileId;
commentParams.pointedPubId = testPub.pubId;
commentParams.pointedProfileId = testPub.profileId;
vm.prank(publisher.owner);
uint256 pubId = hub.comment(commentParams);
console.log(
'Created COMMENT: (%s) <= (%s)',
string.concat(vm.toString(testPub.profileId), ', ', vm.toString(testPub.pubId)),
string.concat(vm.toString(publisher.profileId), ', ', vm.toString(pubId))
);
return TestPublication(publisher.profileId, pubId);
}
function quote(TestPublication memory testPub) internal returns (TestPublication memory) {
uint256 testAccountId = testAccounts.length;
TestAccount memory publisher = _loadAccountAs(string.concat('TESTACCOUNT_', vm.toString(testAccountId)));
testAccounts.push(publisher);
Types.QuoteParams memory quoteParams = _getDefaultQuoteParams();
quoteParams.profileId = publisher.profileId;
quoteParams.pointedPubId = testPub.pubId;
quoteParams.pointedProfileId = testPub.profileId;
vm.prank(publisher.owner);
uint256 pubId = hub.quote(quoteParams);
console.log(
'Created QUOTE: (%s) <= (%s)',
string.concat(vm.toString(testPub.profileId), ', ', vm.toString(testPub.pubId)),
string.concat(vm.toString(publisher.profileId), ', ', vm.toString(pubId))
);
return TestPublication(publisher.profileId, pubId);
}
////// setup////
/// create a big tree with all possible situations (V2 posts)
/// We can use some custom data structure to simplify the tree handling, or just rely on "pointedTo" in pubs.
///
////// function replaceV1(depth) ///
/// function that will convert a given depth of the V2 tree into V1 (starting from the root Post)
///
////// function testReferralsWorkV2() ///
/// a function that takes each node of the V2 tree as target (except mirrors), and permutates with all possible referrers
/// (or makes an array of all other nodes as referrers and passes then all together).
/// Then it checks that the referral system works as expected (i.e. modules are called with the same array of referrals).
///
////// function testReferralsV1() ///
/// a function that takes a V2 tree, and converts it to V1 tree gradually, starting with root Post, then level 1 from it, level 2, etc.
/// At each step, it checks that you can only refer the direct link (pointing to), as this is the only thing possible in V1
/// It does this by picking a random node from the tree as target, and then picking the rest of the nodes as referrers,
/// and expecting them to be passed or failed, depending if they're direct or complex.
///
// Negatives
function testCannotExecuteOperationIf_ReferralProfileIdsPassedQty_DiffersFromPubIdsQty() public {
// TODO - Errors.ArrayMismatch();
}
function testCannotPass_APublicationDoneByItself_AsReferrer() public {
// TODO - Errors.InvalidReferrer();
}
function testCannotPass_Itself_AsReferrer() public {
// TODO - Errors.InvalidReferrer();
}
function testCannotPass_UnexistentProfile_AsReferrer() public {
// TODO - Errors.InvalidReferrer();
}
function testCannotPass_UnexistentPublication_AsReferrer() public {
// TODO
}
function testCannotPass_AMirror_AsReferrer_IfNotPointingToTheTargetPublication() public {
// TODO
}
function testCannotPass_AComment_AsReferrer_IfNotPointingToTheTargetPublication() public {
// TODO
}
// Scenarios
// This test might fail at some point when we check for duplicates!
function testPassingDuplicatedReferralsIsAllowed() public {
// TODO
}
}