Files
core/test/base/TestSetup.t.sol
2023-10-27 13:29:58 -03:00

636 lines
26 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import 'forge-std/Test.sol';
// Deployments
import {Types} from 'contracts/libraries/constants/Types.sol';
import {Errors} from 'contracts/libraries/constants/Errors.sol';
import {Events} from 'contracts/libraries/constants/Events.sol';
import {ArrayHelpers} from 'test/helpers/ArrayHelpers.sol';
import {Typehash} from 'contracts/libraries/constants/Typehash.sol';
import {MetaTxLib} from 'contracts/libraries/MetaTxLib.sol';
import {StorageLib} from 'contracts/libraries/StorageLib.sol';
import 'test/Constants.sol';
import {LibString} from 'solady/utils/LibString.sol';
import {ContractAddressesLoaderDeployer} from 'test/base/ContractAddressesLoaderDeployer.t.sol';
import {LensHub} from 'contracts/LensHub.sol';
import {LensHubInitializable} from 'contracts/misc/LensHubInitializable.sol';
import {FollowNFT} from 'contracts/FollowNFT.sol';
import {LegacyCollectNFT} from 'contracts/misc/LegacyCollectNFT.sol';
import {TransparentUpgradeableProxy} from '@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol';
import {LensHandles} from 'contracts/namespaces/LensHandles.sol';
import {TokenHandleRegistry} from 'contracts/namespaces/TokenHandleRegistry.sol';
import {MockActionModule} from 'test/mocks/MockActionModule.sol';
import {MockReferenceModule} from 'test/mocks/MockReferenceModule.sol';
import {ModuleRegistry} from 'contracts/misc/ModuleRegistry.sol';
import {ILensGovernable} from 'contracts/interfaces/ILensGovernable.sol';
// TODO: Move these to Interface file in test folder.
struct OldCreateProfileParams {
address to;
string handle;
string imageURI;
address followModule;
bytes followModuleInitData;
string followNFTURI;
}
struct OldMirrorData {
uint256 profileId;
uint256 pointedProfileId;
uint256 pointedPubId;
bytes referenceModuleData;
address referenceModule;
bytes referenceModuleInitData;
}
struct OldPostData {
uint256 profileId;
string contentURI;
address collectModule;
bytes collectModuleInitData;
address referenceModule;
bytes referenceModuleInitData;
}
struct OldCommentData {
uint256 profileId;
string contentURI;
uint256 profileIdPointed;
uint256 pubIdPointed;
bytes referenceModuleData;
address collectModule;
bytes collectModuleInitData;
address referenceModule;
bytes referenceModuleInitData;
}
struct OldProfileStruct {
uint256 pubCount;
address followModule;
address followNFT;
string handle;
string imageURI;
string followNFTURI;
}
interface IOldHub {
function createProfile(OldCreateProfileParams memory createProfileParams) external returns (uint256);
function follow(uint256[] calldata profileIds, bytes[] calldata datas) external returns (uint256[] memory);
function collect(uint256 profileId, uint256 pubId, bytes calldata data) external returns (uint256);
function post(OldPostData calldata vars) external returns (uint256);
function comment(OldCommentData calldata vars) external returns (uint256);
function mirror(OldMirrorData memory createProfileParams) external returns (uint256);
function getProfile(uint256 profileId) external view returns (OldProfileStruct memory);
function getCollectNFTImpl() external view returns (address);
}
contract TestSetup is Test, ContractAddressesLoaderDeployer, ArrayHelpers {
using stdJson for string;
function testTestSetup() public {
// Prevents being counted in Foundry Coverage
}
function loadBaseAddresses(string memory targetEnv) internal virtual {
console.log('targetEnv:', targetEnv);
lensVersion = forkVersion;
hubProxyAddr = json.readAddress(string(abi.encodePacked('.', targetEnv, '.LensHubProxy')));
vm.label(hubProxyAddr, 'LENS_HUB');
console.log('hubProxyAddr:', hubProxyAddr);
hub = LensHub(hubProxyAddr);
console.log('Hub:', address(hub));
address followNFTAddr = hub.getFollowNFTImpl();
address legacyCollectNFTAddr;
if (lensVersion == 2) {
legacyCollectNFTAddr = hub.getLegacyCollectNFTImpl();
} else {
console.log('lensVersion is: %s. Trying to getCollectNFTImpl...', lensVersion);
legacyCollectNFTAddr = IOldHub(address(hub)).getCollectNFTImpl();
}
address hubImplAddr = address(uint160(uint256(vm.load(hubProxyAddr, PROXY_IMPLEMENTATION_STORAGE_SLOT))));
console.log('Found hubImplAddr:', hubImplAddr);
hubImpl = LensHubInitializable(hubImplAddr);
followNFT = FollowNFT(followNFTAddr);
legacyCollectNFT = LegacyCollectNFT(legacyCollectNFTAddr);
hubAsProxy = TransparentUpgradeableProxy(payable(address(hub)));
governanceMultisig = hub.getGovernance();
vm.label(governanceMultisig, 'GOVERNANCE_MULTISIG');
governance = governanceMultisig; // TODO: Temporary, look at ContractAddresses.sol for context
deployer = _loadAddressAs('DEPLOYER');
migrationAdmin = _loadAddressAs('MIGRATION_ADMIN');
if (lensVersion == 2) {
treasury = hub.getTreasury();
vm.label(treasury, 'TREASURY');
TREASURY_FEE_BPS = hub.getTreasuryFee();
} else {
ILensGovernable moduleGlobals = ILensGovernable(
json.readAddress(string(abi.encodePacked('.', targetEnv, '.ModuleGlobals')))
);
vm.label(address(moduleGlobals), 'ModuleGlobals');
console.log('ModuleGlobals: %s', address(moduleGlobals));
treasury = moduleGlobals.getTreasury();
console.log('Real Treasury: %s', treasury);
TREASURY_FEE_BPS = moduleGlobals.getTreasuryFee();
console.log('Real Treasury Fee: %s', TREASURY_FEE_BPS);
}
proxyAdmin = address(uint160(uint256(vm.load(hubProxyAddr, ADMIN_SLOT))));
vm.label(proxyAdmin, 'HUB_PROXY_ADMIN');
if (keyExists(json, string(abi.encodePacked('.', targetEnv, '.LensHandles')))) {
console.log('LensHandles key does exist');
lensHandles = LensHandles(json.readAddress(string(abi.encodePacked('.', targetEnv, '.LensHandles'))));
} else {
console.log('LensHandles key does not exist');
if (forkVersion == 1) {
console.log('No LensHandles address found - deploying new one');
address lensHandlesImpl = address(
new LensHandles(governanceMultisig, address(hubAsProxy), HANDLE_GUARDIAN_COOLDOWN)
);
vm.label(lensHandlesImpl, 'LENS_HANDLES_IMPL');
// TODO: Replace deployer owner with proxyAdmin.
lensHandles = LensHandles(address(new TransparentUpgradeableProxy(lensHandlesImpl, deployer, '')));
vm.label(address(lensHandles), 'LENS_HANDLES');
} else {
console.log('No LensHandles address found in addressBook, which is required for V2');
revert('No LensHandles address found in addressBook, which is required for V2');
}
}
if (keyExists(json, string(abi.encodePacked('.', targetEnv, '.TokenHandleRegistry')))) {
console.log('TokenHandleRegistry key does exist');
tokenHandleRegistry = TokenHandleRegistry(
json.readAddress(string(abi.encodePacked('.', targetEnv, '.TokenHandleRegistry')))
);
} else {
console.log('TokenHandleRegistry key does not exist');
if (forkVersion == 1) {
address tokenHandleRegistryImpl = address(
new TokenHandleRegistry(address(hubAsProxy), address(lensHandles))
);
vm.label(tokenHandleRegistryImpl, 'TOKEN_HANDLE_REGISTRY_IMPL');
// TODO: Replace deployer owner with proxyAdmin.
tokenHandleRegistry = TokenHandleRegistry(
address(new TransparentUpgradeableProxy(tokenHandleRegistryImpl, deployer, ''))
);
vm.label(address(tokenHandleRegistry), 'TOKEN_HANDLE_REGISTRY');
} else {
console.log('No TokenHandleRegistry address found in addressBook, which is required for V2');
revert('No TokenHandleRegistry address found in addressBook, which is required for V2');
}
}
loadOrDeploy_GovernanceContract();
loadOrDeploy_ProxyAdminContract();
loadOrDeploy_ModuleRegistryContract();
if (lensVersion == 1) {
vm.prank(governance);
hub.whitelistProfileCreator(address(this), true);
beforeUpgrade();
upgradeToV2();
}
if (forkVersion == 2) {
lensVersion = 2;
}
vm.startPrank(deployer);
// Deploy the MockActionModule.
mockActionModule = new MockActionModule();
vm.label(address(mockActionModule), 'MOCK_ACTION_MODULE');
// Deploy the MockReferenceModule.
mockReferenceModule = new MockReferenceModule();
vm.label(address(mockReferenceModule), 'MOCK_REFERENCE_MODULE');
vm.stopPrank();
///////////////////////////////////////// End deployments.
}
function beforeUpgrade() internal virtual {
// Override to execute Lens V1 state setup.
}
function upgradeToV2() internal virtual {
// Precompute needed addresses.
address followNFTImplAddr = computeCreateAddress(deployer, vm.getNonce(deployer) + 1);
address legacyCollectNFTImplAddr = computeCreateAddress(deployer, vm.getNonce(deployer) + 2);
vm.startPrank(deployer);
// Deploy implementation contracts.
// TODO: Last 3 addresses are for the follow modules for migration purposes.
hubImpl = new LensHubInitializable({ // TODO: Should we use the usual LensHub, not Initializable?
followNFTImpl: followNFTImplAddr,
collectNFTImpl: legacyCollectNFTImplAddr,
moduleRegistry: address(moduleRegistry),
tokenGuardianCooldown: PROFILE_GUARDIAN_COOLDOWN,
migrationParams: Types.MigrationParams({
lensHandlesAddress: address(lensHandles),
tokenHandleRegistryAddress: address(tokenHandleRegistry),
legacyFeeFollowModule: address(0), // TODO: Fill this in
legacyProfileFollowModule: address(0), // TODO: Fill this in
newFeeFollowModule: address(0), // TODO: Fill this in
migrationAdmin: migrationAdmin
})
});
followNFT = new FollowNFT(hubProxyAddr);
legacyCollectNFT = new LegacyCollectNFT(hubProxyAddr);
vm.stopPrank();
// Upgrade the hub.
TransparentUpgradeableProxy oldHubAsProxy = TransparentUpgradeableProxy(payable(hubProxyAddr));
vm.prank(proxyAdmin);
oldHubAsProxy.upgradeTo(address(hubImpl));
vm.startPrank(governance);
hub.setTreasury(treasury);
hub.setTreasuryFee(TREASURY_FEE_BPS);
vm.stopPrank();
lensVersion = 2;
}
function deployBaseContracts() internal {
deployer = _loadAddressAs('DEPLOYER');
governanceMultisig = _loadAddressAs('GOVERNANCE_MULTISIG');
governance = governanceMultisig; // TODO: Temporary, look at ContractAddresses.sol for context
treasury = _loadAddressAs('TREASURY');
migrationAdmin = _loadAddressAs('MIGRATION_ADMIN');
TREASURY_FEE_BPS = 50;
///////////////////////////////////////// Start deployments.
vm.startPrank(deployer);
// Deploy ModuleRegistry implementation and proxy.
address moduleRegistryImpl = address(new ModuleRegistry());
vm.label(moduleRegistryImpl, 'MODULE_REGISTRY_IMPL');
moduleRegistry = ModuleRegistry(address(new TransparentUpgradeableProxy(moduleRegistryImpl, deployer, '')));
vm.label(address(moduleRegistry), 'MODULE_REGISTRY');
// Precompute needed addresses.
address followNFTImplAddr = computeCreateAddress(deployer, vm.getNonce(deployer) + 1);
address legacyCollectNFTImplAddr = computeCreateAddress(deployer, vm.getNonce(deployer) + 2);
hubProxyAddr = computeCreateAddress(deployer, vm.getNonce(deployer) + 3);
address lensHandlesImplAddr = computeCreateAddress(deployer, vm.getNonce(deployer) + 4);
address lensHandlesProxyAddr = computeCreateAddress(deployer, vm.getNonce(deployer) + 5);
address tokenHandleRegistryImplAddr = computeCreateAddress(deployer, vm.getNonce(deployer) + 6);
address tokenHandleRegistryProxyAddr = computeCreateAddress(deployer, vm.getNonce(deployer) + 7);
// Deploy implementation contracts.
// TODO: Last 3 addresses are for the follow modules for migration purposes.
hubImpl = new LensHubInitializable({
followNFTImpl: followNFTImplAddr,
collectNFTImpl: legacyCollectNFTImplAddr,
moduleRegistry: address(moduleRegistry),
tokenGuardianCooldown: PROFILE_GUARDIAN_COOLDOWN,
migrationParams: Types.MigrationParams({
lensHandlesAddress: lensHandlesProxyAddr,
tokenHandleRegistryAddress: tokenHandleRegistryProxyAddr,
legacyFeeFollowModule: address(0),
legacyProfileFollowModule: address(0),
newFeeFollowModule: address(0),
migrationAdmin: migrationAdmin
})
});
followNFT = new FollowNFT(hubProxyAddr);
legacyCollectNFT = new LegacyCollectNFT(hubProxyAddr);
// Deploy and initialize proxy.
bytes memory initData = abi.encodeCall(
hubImpl.initialize,
('Lens Protocol Profiles', 'LPP', governanceMultisig) // TODO: Replace this with GovernanceContract
);
// TODO: Replace deployer owner with proxyAdmin.
hubAsProxy = new TransparentUpgradeableProxy(address(hubImpl), deployer, initData);
// Deploy LensHandles implementation.
address lensHandlesImpl = address(
new LensHandles(governanceMultisig, address(hubAsProxy), HANDLE_GUARDIAN_COOLDOWN)
);
assertEq(lensHandlesImpl, lensHandlesImplAddr);
vm.label(lensHandlesImpl, 'LENS_HANDLES_IMPL');
// TODO: Replace deployer owner with proxyAdmin.
lensHandles = LensHandles(address(new TransparentUpgradeableProxy(lensHandlesImpl, deployer, '')));
assertEq(address(lensHandles), lensHandlesProxyAddr);
vm.label(address(lensHandles), 'LENS_HANDLES');
// Deploy TokenHandleRegistry implementation.
address tokenHandleRegistryImpl = address(new TokenHandleRegistry(address(hubAsProxy), lensHandlesProxyAddr));
assertEq(tokenHandleRegistryImpl, tokenHandleRegistryImplAddr);
vm.label(tokenHandleRegistryImpl, 'TOKEN_HANDLE_REGISTRY_IMPL');
// TODO: Replace deployer owner with proxyAdmin.
tokenHandleRegistry = TokenHandleRegistry(
address(new TransparentUpgradeableProxy(tokenHandleRegistryImpl, deployer, ''))
);
assertEq(address(tokenHandleRegistry), tokenHandleRegistryProxyAddr);
vm.label(address(tokenHandleRegistry), 'TOKEN_HANDLE_REGISTRY');
// Cast proxy to LensHub interface.
hub = LensHub(address(hubAsProxy));
vm.label(address(hub), 'LENS_HUB');
proxyAdmin = address(uint160(uint256(vm.load(hubProxyAddr, ADMIN_SLOT))));
vm.label(proxyAdmin, 'HUB_PROXY_ADMIN');
// Deploy the MockActionModule.
mockActionModule = new MockActionModule();
vm.label(address(mockActionModule), 'MOCK_ACTION_MODULE');
// Deploy the MockReferenceModule.
mockReferenceModule = new MockReferenceModule();
vm.label(address(mockReferenceModule), 'MOCK_REFERENCE_MODULE');
vm.stopPrank();
///////////////////////////////////////// End deployments.
vm.startPrank(governance);
hub.setTreasury(treasury);
hub.setTreasuryFee(TREASURY_FEE_BPS);
vm.stopPrank();
lensVersion = 2;
}
function setUp() public virtual override {
if (__setUpDone) {
// Avoid setUp to be run more than once.
return;
}
super.setUp();
if (bytes(forkEnv).length > 0) {
loadBaseAddresses(forkEnv);
} else {
deployBaseContracts();
}
///////////////////////////////////////// Start governance actions.
vm.startPrank(governanceMultisig);
if (hub.getState() != Types.ProtocolState.Unpaused) {
hub.setState(Types.ProtocolState.Unpaused);
}
// Whitelist the test contract as a profile creator
hub.whitelistProfileCreator(address(this), true);
vm.stopPrank();
///////////////////////////////////////// End governance actions.
domainSeparator = keccak256(
abi.encode(
Typehash.EIP712_DOMAIN,
keccak256('Lens Protocol Profiles'),
MetaTxLib.EIP712_DOMAIN_VERSION_HASH,
block.chainid,
hubProxyAddr
)
);
if (lensVersion == 2) {
defaultAccount = _loadAccountAs('DEFAULT_ACCOUNT');
defaultPub = _loadDefaultPublication();
}
if (lensVersion == 0) {
console.log("LensVersion is 0 - something's not right");
revert("LensVersion is 0 - something's not right");
}
// Avoid setUp to be run more than once.
__setUpDone = true;
console.log("TestSetup's setUp() done");
}
function _createProfile(address profileOwner) internal returns (uint256) {
Types.CreateProfileParams memory createProfileParams = _getDefaultCreateProfileParams();
createProfileParams.to = profileOwner;
console.log('CREATING PROFILE');
return hub.createProfile(createProfileParams);
}
function _createProfile(address profileOwner, string memory handle) internal returns (uint256) {
OldCreateProfileParams memory oldCreateProfileParams = OldCreateProfileParams({
to: profileOwner,
handle: LibString.lower(handle),
imageURI: string.concat(MOCK_URI, '/imageURI/', LibString.lower(handle)),
followModule: address(0),
followModuleInitData: '',
followNFTURI: string.concat(MOCK_URI, '/followNFTURI/', LibString.lower(handle))
});
uint256 profileId = IOldHub(address(hub)).createProfile(oldCreateProfileParams);
console.log('CREATING V1 PROFILE: %s (Profile#%s)', LibString.lower(handle), profileId);
return profileId;
}
function _loadAccountAs(string memory accountLabel) internal returns (TestAccount memory) {
return _loadAccountAs({accountLabel: accountLabel, requireCustomProfileOnFork: false});
}
function _loadAccountAs(
string memory accountLabel,
bool requireCustomProfileOnFork
) internal returns (TestAccount memory) {
// We derive a new account from the given label.
(address accountOwner, uint256 accountOwnerPk) = makeAddrAndKey(accountLabel);
uint256 accountProfileId;
if (fork) {
// If testing in a fork, load the desired profile from .env and transfer it to the derived account.
accountProfileId = vm.envOr({
name: string.concat('FORK_TEST_ACCOUNT__', accountLabel, '__PROFILE_ID'),
defaultValue: uint256(0)
});
// If the custom profile wasn't founde in the .env file and it was required, reverts.
if (accountProfileId == 0 && requireCustomProfileOnFork) {
revert(
string.concat(
'Custom profile not set for ',
accountLabel,
'. Add ',
string.concat('FORK_TEST_ACCOUNT__', accountLabel, '__PROFILE_ID'),
' env variable or set `requireCustomProfileOnFork` as false for it.'
)
);
}
}
if (accountProfileId != 0) {
// If profile was loaded from .env, we transfer it to the generated account. This is needed as otherwise we
// won't have the private key of the owner, which is needed for signing meta-tx in some tests.
address currentProfileOwner = hub.ownerOf(accountProfileId);
vm.startPrank(currentProfileOwner);
if (hub.getTokenGuardianDisablingTimestamp(currentProfileOwner) == 0) {
hub.DANGER__disableTokenGuardian();
}
if (hub.getTokenGuardianDisablingTimestamp(currentProfileOwner) > block.timestamp) {
vm.warp(hub.getTokenGuardianDisablingTimestamp(currentProfileOwner));
}
hub.transferFrom(currentProfileOwner, accountOwner, accountProfileId);
vm.stopPrank();
} else {
// If profile was not loaded yet, we create a fresh one.
if (lensVersion == 1) {
accountProfileId = _createProfile(accountOwner, accountLabel);
} else if (lensVersion == 2) {
accountProfileId = _createProfile(accountOwner);
} else {
console.log('Lens version %s is not supported', lensVersion);
revert('Lens version not supported');
}
}
return TestAccount({ownerPk: accountOwnerPk, owner: accountOwner, profileId: accountProfileId});
}
function _loadDefaultPublication() internal returns (TestPublication memory) {
if (fork) {
// If testing in a fork, try loading the profile ID from .env file.
uint256 profileId = vm.envOr({name: 'FORK_TEST_PUB__DEFAULT__PROFILE_ID', defaultValue: uint256(0)});
if (profileId != 0) {
// If profile ID was in the .env file, pub ID must be there too, otherwise fail.
uint256 pubId = vm.envUint('FORK_TEST_PUB__DEFAULT__PUB_ID');
Types.PublicationType loadedPubType = hub.getPublicationType(profileId, pubId);
if (loadedPubType == Types.PublicationType.Nonexistent) {
revert('Default publication loaded from .env file does not exist in the fork you are testing on.');
} else if (loadedPubType == Types.PublicationType.Mirror) {
// As you cannot reference a mirror or act on it.
revert('Default publication loaded from .env file cannot be a mirror.');
}
return TestPublication(profileId, pubId);
}
}
vm.prank(defaultAccount.owner);
return TestPublication(defaultAccount.profileId, hub.post(_getDefaultPostParams()));
}
function _loadAddressAs(string memory addressLabel) internal returns (address) {
address loadedAddress;
if (fork) {
loadedAddress = vm.envOr({
name: string.concat('FORK__', addressLabel, '__ADDRESS'),
defaultValue: address(0)
});
if (loadedAddress != address(0)) {
vm.label(loadedAddress, addressLabel);
return loadedAddress;
}
}
return makeAddr(addressLabel);
}
function _getNextProfileId() internal view returns (uint256) {
return uint256(vm.load(hubProxyAddr, bytes32(uint256(StorageLib.PROFILE_COUNTER_SLOT)))) + 1;
}
function _getDefaultCreateProfileParams() internal view returns (Types.CreateProfileParams memory) {
return
Types.CreateProfileParams({to: defaultAccount.owner, followModule: address(0), followModuleInitData: ''});
}
function _getDefaultPostParams() internal view returns (Types.PostParams memory) {
return
Types.PostParams({
profileId: defaultAccount.profileId,
contentURI: MOCK_URI,
actionModules: _toAddressArray(address(mockActionModule)),
actionModulesInitDatas: _toBytesArray(abi.encode(true)),
referenceModule: address(0),
referenceModuleInitData: ''
});
}
function _getDefaultCommentParams() internal view returns (Types.CommentParams memory) {
return
Types.CommentParams({
profileId: defaultAccount.profileId,
contentURI: MOCK_URI,
pointedProfileId: defaultPub.profileId,
pointedPubId: defaultPub.pubId,
referrerProfileIds: _emptyUint256Array(),
referrerPubIds: _emptyUint256Array(),
referenceModuleData: '',
actionModules: _toAddressArray(address(mockActionModule)),
actionModulesInitDatas: _toBytesArray(abi.encode(true)),
referenceModule: address(0),
referenceModuleInitData: ''
});
}
function _getDefaultMirrorParams() internal view returns (Types.MirrorParams memory) {
return
Types.MirrorParams({
profileId: defaultAccount.profileId,
metadataURI: '',
pointedProfileId: defaultPub.profileId,
pointedPubId: defaultPub.pubId,
referrerProfileIds: _emptyUint256Array(),
referrerPubIds: _emptyUint256Array(),
referenceModuleData: ''
});
}
function _getDefaultQuoteParams() internal view returns (Types.QuoteParams memory) {
return
Types.QuoteParams({
profileId: defaultAccount.profileId,
contentURI: MOCK_URI,
pointedProfileId: defaultPub.profileId,
pointedPubId: defaultPub.pubId,
referrerProfileIds: _emptyUint256Array(),
referrerPubIds: _emptyUint256Array(),
referenceModuleData: '',
actionModules: _toAddressArray(address(mockActionModule)),
actionModulesInitDatas: _toBytesArray(abi.encode(true)),
referenceModule: address(0),
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)
});
}
}