feat: (WIP) Initial setup of fork upgrade test, also removed use of freeCollectModule.

This commit is contained in:
zer0dot
2022-10-12 11:52:19 -04:00
parent fd252dcfa2
commit ec3afcb545
7 changed files with 332 additions and 33 deletions

View File

@@ -0,0 +1,43 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import {ICollectModule} from '../interfaces/ICollectModule.sol';
/**
* @title FreeCollectModule
* @author Lens Protocol
*
* @notice This is a simple Lens CollectModule implementation, inheriting from the ICollectModule interface.
*
* This module works by allowing all collects.
*/
contract MockCollectModule is ICollectModule {
/**
* @dev There is nothing needed at initialization.
*/
function initializePublicationCollectModule(
uint256,
address,
uint256,
bytes calldata data
) external pure override returns (bytes memory) {
uint256 number = abi.decode(data, (uint256));
require(number == 1, 'MockReferenceModule: invalid');
return new bytes(0);
}
/**
* @dev Processes a collect by:
* 1. Ensuring the collector is a follower, if needed
*/
function processCollect(
uint256,
uint256,
address collector,
address,
uint256 profileId,
uint256 pubId,
bytes calldata
) external view override {}
}

View File

@@ -0,0 +1,40 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import {IDeprecatedCollectModule} from '../interfaces/IDeprecatedCollectModule.sol';
/**
* @title FreeCollectModule
* @author Lens Protocol
*
* @notice This is a simple Lens CollectModule implementation, inheriting from the ICollectModule interface.
*
* This module works by allowing all collects.
*/
contract MockDeprecatedCollectModule is IDeprecatedCollectModule {
/**
* @dev There is nothing needed at initialization.
*/
function initializePublicationCollectModule(
uint256,
uint256,
bytes calldata data
) external pure override returns (bytes memory) {
uint256 number = abi.decode(data, (uint256));
require(number == 1, 'MockReferenceModule: invalid');
return new bytes(0);
}
/**
* @dev Processes a collect by:
* 1. Ensuring the collector is a follower, if needed
*/
function processCollect(
uint256,
address collector,
uint256 profileId,
uint256 pubId,
bytes calldata
) external view override {}
}

View File

@@ -0,0 +1,40 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import {IDeprecatedFollowModule} from '../interfaces/IDeprecatedFollowModule.sol';
/**
* @dev This is a simple mock follow module to be used for testing.
*/
contract MockDeprecatedFollowModule is IDeprecatedFollowModule {
function initializeFollowModule(
uint256,
bytes calldata data
) external pure override returns (bytes memory) {
uint256 number = abi.decode(data, (uint256));
require(number == 1, 'MockFollowModule: invalid');
return new bytes(0);
}
function processFollow(
address follower,
uint256 profileId,
bytes calldata data
) external override {}
function isFollowing(
uint256,
address,
uint256
) external pure override returns (bool) {
return true;
}
function followModuleTransferHook(
uint256 profileId,
address from,
address to,
uint256 followNFTTokenId
) external override {}
}

View File

@@ -0,0 +1,34 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import {IDeprecatedReferenceModule} from '../interfaces/IDeprecatedReferenceModule.sol';
/**
* @dev This is a simple mock follow module to be used for testing.
*/
contract MockDeprecatedReferenceModule is IDeprecatedReferenceModule {
function initializeReferenceModule(
uint256,
uint256,
bytes calldata data
) external pure override returns (bytes memory) {
uint256 number = abi.decode(data, (uint256));
require(number == 1, 'MockReferenceModule: invalid');
return new bytes(0);
}
function processComment(
uint256 profileId,
uint256 profileIdPointed,
uint256 pubIdPointed,
bytes calldata data
) external override {}
function processMirror(
uint256 profileId,
uint256 profileIdPointed,
uint256 pubIdPointed,
bytes calldata data
) external override {}
}

View File

@@ -90,8 +90,8 @@ contract PublishingTest is BaseTest {
bytes32 digest = _getPostTypedDataHash(
firstProfileId,
mockURI,
address(freeCollectModule),
abi.encode(false),
address(mockCollectModule),
abi.encode(1),
address(0),
'',
nonce,
@@ -104,8 +104,8 @@ contract PublishingTest is BaseTest {
delegatedSigner: address(0),
profileId: firstProfileId,
contentURI: mockURI,
collectModule: address(freeCollectModule),
collectModuleInitData: abi.encode(false),
collectModule: address(mockCollectModule),
collectModuleInitData: abi.encode(1),
referenceModule: address(0),
referenceModuleInitData: '',
sig: _getSigStruct(otherSignerKey, digest, deadline)
@@ -119,8 +119,8 @@ contract PublishingTest is BaseTest {
bytes32 digest = _getPostTypedDataHash(
firstProfileId,
mockURI,
address(freeCollectModule),
abi.encode(false),
address(mockCollectModule),
abi.encode(1),
address(0),
'',
nonce,
@@ -133,8 +133,8 @@ contract PublishingTest is BaseTest {
delegatedSigner: otherSigner,
profileId: firstProfileId,
contentURI: mockURI,
collectModule: address(freeCollectModule),
collectModuleInitData: abi.encode(false),
collectModule: address(mockCollectModule),
collectModuleInitData: abi.encode(1),
referenceModule: address(0),
referenceModuleInitData: '',
sig: _getSigStruct(otherSignerKey, digest, deadline)
@@ -154,8 +154,8 @@ contract PublishingTest is BaseTest {
firstProfileId,
1,
'',
address(freeCollectModule),
abi.encode(false),
address(mockCollectModule),
abi.encode(1),
address(0),
'',
nonce,
@@ -172,8 +172,8 @@ contract PublishingTest is BaseTest {
profileIdPointed: firstProfileId,
pubIdPointed: 1,
referenceModuleData: '',
collectModule: address(freeCollectModule),
collectModuleInitData: abi.encode(false),
collectModule: address(mockCollectModule),
collectModuleInitData: abi.encode(1),
referenceModule: address(0),
referenceModuleInitData: '',
sig: sig
@@ -193,8 +193,8 @@ contract PublishingTest is BaseTest {
firstProfileId,
1,
'',
address(freeCollectModule),
abi.encode(false),
address(mockCollectModule),
abi.encode(1),
address(0),
'',
nonce,
@@ -211,8 +211,8 @@ contract PublishingTest is BaseTest {
profileIdPointed: firstProfileId,
pubIdPointed: 1,
referenceModuleData: '',
collectModule: address(freeCollectModule),
collectModuleInitData: abi.encode(false),
collectModule: address(mockCollectModule),
collectModuleInitData: abi.encode(1),
referenceModule: address(0),
referenceModuleInitData: '',
sig: sig
@@ -294,8 +294,8 @@ contract PublishingTest is BaseTest {
bytes32 digest = _getPostTypedDataHash(
firstProfileId,
mockURI,
address(freeCollectModule),
abi.encode(false),
address(mockCollectModule),
abi.encode(1),
address(0),
'',
nonce,
@@ -307,8 +307,8 @@ contract PublishingTest is BaseTest {
delegatedSigner: otherSigner,
profileId: firstProfileId,
contentURI: mockURI,
collectModule: address(freeCollectModule),
collectModuleInitData: abi.encode(false),
collectModule: address(mockCollectModule),
collectModuleInitData: abi.encode(1),
referenceModule: address(0),
referenceModuleInitData: '',
sig: _getSigStruct(otherSignerKey, digest, deadline)
@@ -339,8 +339,8 @@ contract PublishingTest is BaseTest {
firstProfileId,
1,
'',
address(freeCollectModule),
abi.encode(false),
address(mockCollectModule),
abi.encode(1),
address(0),
'',
nonce,
@@ -356,8 +356,8 @@ contract PublishingTest is BaseTest {
profileIdPointed: firstProfileId,
pubIdPointed: 1,
referenceModuleData: '',
collectModule: address(freeCollectModule),
collectModuleInitData: abi.encode(false),
collectModule: address(mockCollectModule),
collectModuleInitData: abi.encode(1),
referenceModule: address(0),
referenceModuleInitData: '',
sig: sig

View File

@@ -7,13 +7,13 @@ import 'forge-std/Test.sol';
import '../../../contracts/core/LensHub.sol';
import '../../../contracts/core/FollowNFT.sol';
import '../../../contracts/core/CollectNFT.sol';
import '../../../contracts/core/modules/collect/FreeCollectModule.sol';
import '../../../contracts/upgradeability/TransparentUpgradeableProxy.sol';
import '../../../contracts/libraries/DataTypes.sol';
import '../../../contracts/libraries/Constants.sol';
import '../../../contracts/libraries/Errors.sol';
import '../../../contracts/libraries/GeneralLib.sol';
import '../../../contracts/libraries/ProfileTokenURILogic.sol';
import '../../../contracts/mocks/MockCollectModule.sol';
contract TestSetup is Test {
uint256 constant firstProfileId = 1;
@@ -36,7 +36,7 @@ contract TestSetup is Test {
LensHub hubImpl;
TransparentUpgradeableProxy hubAsProxy;
LensHub hub;
FreeCollectModule freeCollectModule;
MockCollectModule mockCollectModule;
DataTypes.CreateProfileData mockCreateProfileData;
@@ -68,8 +68,8 @@ contract TestSetup is Test {
// Cast proxy to LensHub interface.
hub = LensHub(address(hubAsProxy));
// Deploy the FreeCollectModule.
freeCollectModule = new FreeCollectModule(hubProxyAddr);
// Deploy the MockCollectModule.
mockCollectModule = new MockCollectModule();
// End deployments.
vm.stopPrank();
@@ -81,7 +81,7 @@ contract TestSetup is Test {
hub.setState(DataTypes.ProtocolState.Unpaused);
// Whitelist the FreeCollectModule.
hub.whitelistCollectModule(address(freeCollectModule), true);
hub.whitelistCollectModule(address(mockCollectModule), true);
// Whitelist the test contract as a profile creator
hub.whitelistProfileCreator(me, true);
@@ -114,8 +114,8 @@ contract TestSetup is Test {
mockPostData = DataTypes.PostData({
profileId: firstProfileId,
contentURI: mockURI,
collectModule: address(freeCollectModule),
collectModuleInitData: abi.encode(false),
collectModule: address(mockCollectModule),
collectModuleInitData: abi.encode(1),
referenceModule: address(0),
referenceModuleInitData: ''
});
@@ -127,8 +127,8 @@ contract TestSetup is Test {
profileIdPointed: firstProfileId,
pubIdPointed: 1,
referenceModuleData: '',
collectModule: address(freeCollectModule),
collectModuleInitData: abi.encode(false),
collectModule: address(mockCollectModule),
collectModuleInitData: abi.encode(1),
referenceModule: address(0),
referenceModuleInitData: ''
});

View File

@@ -2,12 +2,23 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import '@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol';
import '@openzeppelin/contracts/token/ERC721/IERC721.sol';
import 'forge-std/console2.sol';
import '../base/BaseTest.t.sol';
import '../../../contracts/mocks/MockReferenceModule.sol';
import '../../../contracts/mocks/MockDeprecatedReferenceModule.sol';
import '../../../contracts/mocks/MockCollectModule.sol';
import '../../../contracts/mocks/MockDeprecatedCollectModule.sol';
import '../../../contracts/mocks/MockFollowModule.sol';
import '../../../contracts/mocks/MockDeprecatedFollowModule.sol';
import '../../../contracts/interfaces/IERC721Time.sol';
contract UpgradeForkTest is BaseTest {
bytes32 constant ADMIN_SLOT = bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1);
address constant POLYGON_HUB_PROXY = 0xDb46d1Dc155634FbC732f92E853b10B288AD5a1d;
address constant MUMBAI_HUB_PROXY = 0x60Ae865ee4C725cd04353b5AAb364553f56ceF82;
uint256 polygonForkId;
uint256 mumbaiForkId;
@@ -31,6 +42,12 @@ contract UpgradeForkTest is BaseTest {
address gov = oldHub.getGovernance();
address proxyAdmin = address(uint160(uint256(vm.load(POLYGON_HUB_PROXY, ADMIN_SLOT))));
// Create a profile on the old hub, set the default profile.
uint256 profileId = _fullCreateProfileSequence(gov, oldHub);
// Post, comment, mirror.
_fullPublishSequence(profileId, gov, oldHub);
// Second, upgrade the hub.
vm.prank(proxyAdmin);
oldHubAsProxy.upgradeTo(address(hubImpl));
@@ -43,4 +60,129 @@ contract UpgradeForkTest is BaseTest {
oldHub.setGovernance(me);
assertEq(oldHub.getGovernance(), me);
}
function _fullPublishSequence(
uint256 profileId,
address gov,
ILensHub hub
) private {
// In order to make this test suite evergreen, we must try publishing with a modern collect and reference
// module since we don't know which version of the hub we're working with. If this fails, then we should
// use deprecated modules.
address mockReferenceModule = address(new MockReferenceModule());
vm.startPrank(gov);
hub.whitelistCollectModule(address(mockCollectModule), true);
hub.whitelistReferenceModule(mockReferenceModule, true);
vm.stopPrank();
// Set the proper profile ID, reference module data, and profile ID pointed.
mockPostData.profileId = profileId;
mockPostData.referenceModuleInitData = abi.encode(1);
mockCommentData.profileId = profileId;
mockCommentData.profileIdPointed = profileId;
mockCommentData.referenceModuleInitData = abi.encode(1);
mockMirrorData.profileId = profileId;
mockMirrorData.profileIdPointed = profileId;
mockMirrorData.referenceModuleInitData = abi.encode(1);
// Set the modern reference module, the modern collect module is already set by default.
mockPostData.referenceModule = mockReferenceModule;
try hub.post(mockPostData) returns (uint256 retPubId) {
console2.log('Post published with modern collect and reference module.');
uint256 postId = retPubId;
assertEq(postId, 1);
} catch {
console2.log(
'Post with modern collect and reference module failed, Attempting with deprecated modules'
);
address mockDeprecatedCollectModule = address(new MockDeprecatedCollectModule());
address mockDeprecatedReferenceModule = address(new MockDeprecatedReferenceModule());
vm.startPrank(gov);
hub.whitelistCollectModule(mockDeprecatedCollectModule, true);
hub.whitelistReferenceModule(mockDeprecatedReferenceModule, true);
vm.stopPrank();
// Post.
mockPostData.collectModule = mockDeprecatedCollectModule;
mockPostData.referenceModule = mockDeprecatedReferenceModule;
uint256 postId = hub.post(mockPostData);
// Validate post.
assertEq(postId, 1);
DataTypes.PublicationStruct memory pub = hub.getPub(profileId, postId);
assertEq(pub.profileIdPointed, 0);
assertEq(pub.pubIdPointed, 0);
assertEq(pub.contentURI, mockPostData.contentURI);
assertEq(pub.referenceModule, mockPostData.referenceModule);
assertEq(pub.collectModule, mockPostData.collectModule);
assertEq(pub.collectNFT, address(0));
// Comment.
mockCommentData.collectModule = mockDeprecatedCollectModule;
mockCommentData.referenceModule = mockDeprecatedReferenceModule;
uint256 commentId = hub.comment(mockCommentData);
// Validate comment.
assertEq(commentId, 2);
pub = hub.getPub(profileId, commentId);
assertEq(pub.profileIdPointed, mockCommentData.profileIdPointed);
assertEq(pub.pubIdPointed, mockCommentData.pubIdPointed);
assertEq(pub.contentURI, mockCommentData.contentURI);
assertEq(pub.referenceModule, mockCommentData.referenceModule);
assertEq(pub.collectModule, mockCommentData.collectModule);
assertEq(pub.collectNFT, address(0));
// Mirror.
mockMirrorData.referenceModule = mockDeprecatedReferenceModule;
uint256 mirrorId = hub.mirror(mockMirrorData);
// Validate mirror.
assertEq(mirrorId, 3);
pub = hub.getPub(profileId, mirrorId);
assertEq(pub.profileIdPointed, mockMirrorData.profileIdPointed);
assertEq(pub.pubIdPointed, mockMirrorData.pubIdPointed);
assertEq(pub.contentURI, '');
assertEq(pub.referenceModule, mockMirrorData.referenceModule);
assertEq(pub.collectModule, address(0));
assertEq(pub.collectNFT, address(0));
}
}
function _fullCreateProfileSequence(address gov, ILensHub hub) private returns (uint256) {
// In order to make this test suite evergreen, we must try setting a modern follow module since we don't know
// which version of the hub we're working with, if this fails, then we should use a deprecated one.
address mockFollowModule = address(new MockFollowModule());
vm.startPrank(gov);
hub.whitelistProfileCreator(me, true);
hub.whitelistFollowModule(mockFollowModule, true);
vm.stopPrank();
mockCreateProfileData.to = me;
mockCreateProfileData.handle = vm.toString(IERC721Enumerable(address(hub)).totalSupply());
mockCreateProfileData.followModule = mockFollowModule;
mockCreateProfileData.followModuleInitData = abi.encode(1);
uint256 profileId;
try hub.createProfile(mockCreateProfileData) returns (uint256 retProfileId) {
profileId = retProfileId;
console2.log('Profile created with modern follow module.');
} catch {
console2.log(
'Profile creation with modern follow module failed. Attempting with deprecated module.'
);
address mockDeprecatedFollowModule = address(new MockDeprecatedFollowModule());
vm.prank(gov);
hub.whitelistFollowModule(mockDeprecatedFollowModule, true);
mockCreateProfileData.followModule = mockDeprecatedFollowModule;
profileId = hub.createProfile(mockCreateProfileData);
}
return profileId;
}
}