Merge pull request #77 from lens-protocol/test/act

misc: Act tests added
This commit is contained in:
Alan
2023-05-03 18:31:55 +01:00
committed by GitHub
4 changed files with 233 additions and 13 deletions

View File

@@ -20,10 +20,6 @@ library ActionLib {
byProfile: publicationActionParams.publicationActedProfileId
});
if (publicationActionParams.publicationActedId == 0) {
revert Errors.PublicationDoesNotExist();
}
Types.Publication storage _actedOnPublication = StorageLib.getPublication(
publicationActionParams.publicationActedProfileId,
publicationActionParams.publicationActedId
@@ -32,12 +28,9 @@ library ActionLib {
address actionModuleAddress = publicationActionParams.actionModuleAddress;
uint256 actionModuleId = StorageLib.actionModuleWhitelistData()[actionModuleAddress].id;
if (actionModuleId == 0) {
revert Errors.ActionNotAllowed();
}
if (!_isActionAllowed(_actedOnPublication, actionModuleId)) {
if (!_isActionEnabled(_actedOnPublication, actionModuleId)) {
// This will also revert for:
// - Non-existent action modules
// - Non-existent publications
// - Legacy V1 publications
// Because the storage will be empty.
@@ -69,8 +62,14 @@ library ActionLib {
return actionModuleReturnData;
}
function _isActionAllowed(Types.Publication storage _publication, uint256 actionId) private view returns (bool) {
uint256 actionIdBitmapMask = 1 << (actionId - 1);
return actionIdBitmapMask & _publication.actionModulesBitmap != 0;
function _isActionEnabled(
Types.Publication storage _publication,
uint256 actionModuleId
) private view returns (bool) {
if (actionModuleId == 0) {
return false;
}
uint256 actionModuleIdBitmapMask = 1 << (actionModuleId - 1);
return actionModuleIdBitmapMask & _publication.actionModulesBitmap != 0;
}
}

208
test/ActTest.t.sol Normal file
View File

@@ -0,0 +1,208 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import 'test/base/BaseTest.t.sol';
import 'test/MetaTxNegatives.t.sol';
import {ILensHub} from 'contracts/interfaces/ILensHub.sol';
import {Types} from 'contracts/libraries/constants/Types.sol';
import {Events} from 'contracts/libraries/constants/Events.sol';
contract ActTest is BaseTest {
TestAccount actor;
Types.PublicationActionParams defaultPubActionParams;
function setUp() public virtual override {
super.setUp();
actor = _loadAccountAs('ACTOR');
defaultPubActionParams = _getDefaultPublicationActionParams();
defaultPubActionParams.actorProfileId = actor.profileId;
}
// Negatives
function testCannotAct_ifNonExistingPublication(uint256 nonexistentPubId) public {
vm.assume(nonexistentPubId != defaultPub.pubId);
defaultPubActionParams.publicationActedId = nonexistentPubId;
vm.expectRevert(Errors.ActionNotAllowed.selector);
_act(actor.ownerPk, defaultPubActionParams);
}
function testCannotAct_ifActionModuleNotEnabledForPublication(address notEnabledActionModule) public {
vm.assume(notEnabledActionModule != address(mockActionModule));
defaultPubActionParams.actionModuleAddress = notEnabledActionModule;
vm.expectRevert(Errors.ActionNotAllowed.selector);
_act(actor.ownerPk, defaultPubActionParams);
}
function testCannotAct_ifProtocolIsPaused() public {
vm.prank(governance);
hub.setState(Types.ProtocolState.Paused);
vm.expectRevert(Errors.Paused.selector);
_act(actor.ownerPk, defaultPubActionParams);
}
function testCannotAct_onMirrors() public {
Types.MirrorParams memory mirrorParams = _getDefaultMirrorParams();
vm.prank(defaultAccount.owner);
uint256 mirrorPubId = hub.mirror(mirrorParams);
defaultPubActionParams.publicationActedId = mirrorPubId;
vm.expectRevert(Errors.ActionNotAllowed.selector);
_act(actor.ownerPk, defaultPubActionParams);
}
// Scenarios
function testAct() public {
vm.expectEmit(true, true, true, true, address(hub));
emit Events.Acted(defaultPubActionParams, abi.encode(true), block.timestamp);
Types.ProcessActionParams memory processActionParams = Types.ProcessActionParams({
publicationActedProfileId: defaultPubActionParams.publicationActedProfileId,
publicationActedId: defaultPubActionParams.publicationActedId,
actorProfileId: defaultPubActionParams.actorProfileId,
actorProfileOwner: actor.owner,
transactionExecutor: actor.owner,
referrerProfileIds: defaultPubActionParams.referrerProfileIds,
referrerPubIds: defaultPubActionParams.referrerPubIds,
referrerPubTypes: _emptyPubTypesArray(),
actionModuleData: defaultPubActionParams.actionModuleData
});
vm.expectCall(
address(mockActionModule),
abi.encodeWithSelector(mockActionModule.processPublicationAction.selector, (processActionParams))
);
_act(actor.ownerPk, defaultPubActionParams);
}
function testAct_onComment() public {
Types.CommentParams memory commentParams = _getDefaultCommentParams();
vm.prank(defaultAccount.owner);
uint256 commentPubId = hub.comment(commentParams);
defaultPubActionParams.publicationActedId = commentPubId;
testAct();
}
function testAct_onQuote() public {
Types.QuoteParams memory quoteParams = _getDefaultQuoteParams();
vm.prank(defaultAccount.owner);
uint256 quotePubId = hub.quote(quoteParams);
defaultPubActionParams.publicationActedId = quotePubId;
testAct();
}
function testCanAct_evenIfActionWasUnwhitelisted() public {
vm.prank(governance);
hub.whitelistActionModule(defaultPubActionParams.actionModuleAddress, false);
testAct();
}
function testCanAct_evenIfPublishingPaused() public {
vm.prank(governance);
hub.setState(Types.ProtocolState.PublishingPaused);
testAct();
}
function _act(
uint256 pk,
Types.PublicationActionParams memory publicationActionParams
) internal virtual returns (bytes memory) {
vm.prank(vm.addr(pk));
return hub.act(publicationActionParams);
}
function _refreshCachedNonces() internal virtual {
// Nothing to do there.
}
}
contract ActMetaTxTest is ActTest, MetaTxNegatives {
mapping(address => uint256) cachedNonceByAddress;
function testActionMetaTxTest() public {
// Prevents being counted in Foundry Coverage
}
function setUp() public override(ActTest, MetaTxNegatives) {
ActTest.setUp();
MetaTxNegatives.setUp();
cachedNonceByAddress[actor.owner] = hub.nonces(actor.owner);
}
function _act(
uint256 pk,
Types.PublicationActionParams memory publicationActionParams
) internal override returns (bytes memory) {
address signer = vm.addr(pk);
return
hub.actWithSig({
publicationActionParams: publicationActionParams,
signature: _getSigStruct({
pKey: pk,
digest: _calculateActWithSigDigest(
publicationActionParams,
cachedNonceByAddress[signer],
type(uint256).max
),
deadline: type(uint256).max
})
});
}
function _executeMetaTx(uint256 signerPk, uint256 nonce, uint256 deadline) internal virtual override {
hub.actWithSig({
publicationActionParams: defaultPubActionParams,
signature: _getSigStruct({
signer: vm.addr(_getDefaultMetaTxSignerPk()),
pKey: signerPk,
digest: _calculateActWithSigDigest(defaultPubActionParams, nonce, deadline),
deadline: deadline
})
});
}
function _getDefaultMetaTxSignerPk() internal virtual override returns (uint256) {
return actor.ownerPk;
}
function _calculateActWithSigDigest(
Types.PublicationActionParams memory publicationActionParams,
uint256 nonce,
uint256 deadline
) internal view returns (bytes32) {
return
_calculateDigest(
keccak256(
abi.encode(
Typehash.ACT,
publicationActionParams.publicationActedProfileId,
publicationActionParams.publicationActedId,
publicationActionParams.actorProfileId,
publicationActionParams.referrerProfileIds,
publicationActionParams.referrerPubIds,
publicationActionParams.actionModuleAddress,
keccak256(publicationActionParams.actionModuleData),
nonce,
deadline
)
)
);
}
function _refreshCachedNonces() internal override {
cachedNonceByAddress[actor.owner] = hub.nonces(actor.owner);
}
}

View File

@@ -374,4 +374,17 @@ contract TestSetup is Test, ForkManagement, ArrayHelpers {
referenceModuleInitData: ''
});
}
function _getDefaultPublicationActionParams() internal view returns (Types.PublicationActionParams memory) {
return
Types.PublicationActionParams({
publicationActedProfileId: defaultPub.profileId,
publicationActedId: defaultPub.pubId,
actorProfileId: defaultAccount.profileId,
referrerProfileIds: _emptyUint256Array(),
referrerPubIds: _emptyUint256Array(),
actionModuleAddress: address(mockActionModule),
actionModuleData: abi.encode(true)
});
}
}