feat: PublicActProxy - added universal publicPaidAct

This commit is contained in:
vicnaum
2024-05-09 17:38:58 +02:00
parent c07d927d67
commit d7dbb4c68d
3 changed files with 445 additions and 310 deletions

View File

@@ -29,4 +29,6 @@ library Typehash {
bytes32 constant SET_PROFILE_METADATA_URI = keccak256('SetProfileMetadataURI(uint256 profileId,string metadataURI,uint256 nonce,uint256 deadline)');
bytes32 constant UNFOLLOW = keccak256('Unfollow(uint256 unfollowerProfileId,uint256[] idsOfProfilesToUnfollow,uint256 nonce,uint256 deadline)');
bytes32 constant PUBLIC_PAID_ACT = keccak256('PublicPaidAct(uint256 publicationActedProfileId,uint256 publicationActedId,uint256 actorProfileId,uint256[] referrerProfileIds,uint256[] referrerPubIds,address actionModuleAddress,bytes actionModuleData,address currency,uint256 amount,address approveTo,uint256 nonce,uint256 deadline)');
}

View File

@@ -8,7 +8,10 @@ import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {SafeERC20} from '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';
import {CollectPublicationAction} from 'contracts/modules/act/collect/CollectPublicationAction.sol';
import {BaseProfilePublicationData, IBaseFeeCollectModule} from 'contracts/modules/interfaces/IBaseFeeCollectModule.sol';
import {MetaTxLib} from 'contracts/libraries/MetaTxLib.sol';
import {Errors} from 'contracts/libraries/constants/Errors.sol';
import {Events} from 'contracts/libraries/constants/Events.sol';
import {Typehash} from 'contracts/libraries/constants/Typehash.sol';
import {IERC1271} from '@openzeppelin/contracts/interfaces/IERC1271.sol';
interface IProtocolSharedRevenueMinFeeMintModule {
function getMintFeeParams() external view returns (address, uint256);
@@ -19,6 +22,10 @@ interface IProtocolSharedRevenueMinFeeMintModule {
/// @notice This contract allows anyone to Act on a publication without holding a profile
/// @dev This contract holds a profile (or is a DE of that profile) and acts on behalf of the caller
contract PublicActProxy {
string constant EIP712_DOMAIN_VERSION = '2';
bytes32 constant EIP712_DOMAIN_VERSION_HASH = keccak256(bytes(EIP712_DOMAIN_VERSION));
bytes4 constant EIP1271_MAGIC_VALUE = 0x1626ba7e;
using SafeERC20 for IERC20;
ILensHub public immutable HUB;
@@ -59,42 +66,183 @@ contract PublicActProxy {
HUB.act(publicationActionParams);
}
function publicPaidAct(
Types.PublicationActionParams calldata publicationActionParams,
address currency,
uint256 amount,
address approveTo
) external {
_publicAct(publicationActionParams, currency, amount, approveTo, msg.sender);
}
function publicPaidActWithSig(
Types.PublicationActionParams calldata publicationActionParams,
address currency,
uint256 amount,
address approveTo,
Types.EIP712Signature calldata signature
) external {
_validatePaidActSignature(signature, publicationActionParams, PaymentParams(currency, amount, approveTo));
_publicAct(publicationActionParams, currency, amount, approveTo, signature.signer);
}
struct PaymentParams {
address currency;
uint256 amount;
address approveTo;
}
function _validatePaidActSignature(
Types.EIP712Signature calldata signature,
Types.PublicationActionParams calldata publicationActionParams,
PaymentParams memory paymentParams
) internal {
bytes memory encodedAbi = abi.encode(
Typehash.PUBLIC_PAID_ACT,
publicationActionParams.publicationActedProfileId,
publicationActionParams.publicationActedId,
publicationActionParams.actorProfileId,
_encodeUsingEip712Rules(publicationActionParams.referrerProfileIds),
_encodeUsingEip712Rules(publicationActionParams.referrerPubIds),
publicationActionParams.actionModuleAddress,
_encodeUsingEip712Rules(publicationActionParams.actionModuleData),
paymentParams.currency,
paymentParams.amount,
paymentParams.approveTo,
_getNonceIncrementAndEmitEvent(signature.signer),
signature.deadline
);
_validateRecoveredAddress(_calculateDigest(keccak256(encodedAbi)), signature);
}
function _validateActSignature(
Types.EIP712Signature calldata signature,
Types.PublicationActionParams calldata publicationActionParams
) internal {
_validateRecoveredAddress(
_calculateDigest(
keccak256(
abi.encode(
Typehash.ACT,
publicationActionParams.publicationActedProfileId,
publicationActionParams.publicationActedId,
publicationActionParams.actorProfileId,
_encodeUsingEip712Rules(publicationActionParams.referrerProfileIds),
_encodeUsingEip712Rules(publicationActionParams.referrerPubIds),
publicationActionParams.actionModuleAddress,
_encodeUsingEip712Rules(publicationActionParams.actionModuleData),
_getNonceIncrementAndEmitEvent(signature.signer),
signature.deadline
)
)
),
signature
);
}
/**
* @dev Wrapper for ecrecover to reduce code size, used in meta-tx specific functions.
*/
function _validateRecoveredAddress(bytes32 digest, Types.EIP712Signature calldata signature) private view {
if (block.timestamp > signature.deadline) revert Errors.SignatureExpired();
// If the expected address is a contract, check the signature there.
if (signature.signer.code.length != 0) {
bytes memory concatenatedSig = abi.encodePacked(signature.r, signature.s, signature.v);
if (IERC1271(signature.signer).isValidSignature(digest, concatenatedSig) != EIP1271_MAGIC_VALUE) {
revert Errors.SignatureInvalid();
}
} else {
address recoveredAddress = ecrecover(digest, signature.v, signature.r, signature.s);
if (recoveredAddress == address(0) || recoveredAddress != signature.signer) {
revert Errors.SignatureInvalid();
}
}
}
function _encodeUsingEip712Rules(bytes memory bytesValue) private pure returns (bytes32) {
return keccak256(bytesValue);
}
function _encodeUsingEip712Rules(uint256[] memory uint256Array) private pure returns (bytes32) {
return keccak256(abi.encodePacked(uint256Array));
}
/**
* @dev This fetches a signer's current nonce and increments it so it's ready for the next meta-tx. Also emits
* the `NonceUpdated` event.
*
* @param signer The address to get and increment the nonce for.
*
* @return uint256 The current nonce for the given signer prior to being incremented.
*/
function _getNonceIncrementAndEmitEvent(address signer) private returns (uint256) {
uint256 currentNonce;
unchecked {
currentNonce = _nonces[signer]++;
}
emit Events.NonceUpdated(signer, currentNonce + 1, block.timestamp);
return currentNonce;
}
/**
* @dev Calculates EIP712 digest based on the current DOMAIN_SEPARATOR.
*
* @param hashedMessage The message hash from which the digest should be calculated.
*
* @return bytes32 A 32-byte output representing the EIP712 digest.
*/
function _calculateDigest(bytes32 hashedMessage) private view returns (bytes32) {
return keccak256(abi.encodePacked('\x19\x01', _calculateDomainSeparator(), hashedMessage));
}
function _calculateDomainSeparator() internal view returns (bytes32) {
return
keccak256(
abi.encode(
Typehash.EIP712_DOMAIN,
keccak256(bytes(name())),
EIP712_DOMAIN_VERSION_HASH,
block.chainid,
address(this)
)
);
}
// For the paid collect to work, additional steps are required:
// Collector should set enough allowance to this contract to pay for collect NFT
// Funds will be taken from msg.sender
// Funds will be approved from this contract to collectModule found in publication storage
// DEPRECATED:
function publicCollect(Types.PublicationActionParams calldata publicationActionParams) external {
_publicCollect(publicationActionParams, msg.sender);
}
// DEPRECATED:
function publicCollectWithSig(
Types.PublicationActionParams calldata publicationActionParams,
Types.EIP712Signature calldata signature
) external {
MetaTxLib.validateActSignature(signature, publicationActionParams);
_validateActSignature(signature, publicationActionParams);
_publicCollect(publicationActionParams, signature.signer);
}
function publicSharedRevenueCollect(Types.PublicationActionParams calldata publicationActionParams) external {
_publicSharedRevenueCollect(publicationActionParams, msg.sender);
}
// Internal functions
function publicSharedRevenueCollectWithSig(
function _publicAct(
Types.PublicationActionParams calldata publicationActionParams,
Types.EIP712Signature calldata signature
) external {
MetaTxLib.validateActSignature(signature, publicationActionParams);
_publicSharedRevenueCollect(publicationActionParams, signature.signer);
}
function nonces(address signer) public view returns (uint256) {
return _nonces[signer];
}
function incrementNonce(uint8 increment) external {
MetaTxLib.incrementNonce(increment);
address currency,
uint256 amount,
address approveTo,
address transactionExecutor
) internal {
if (amount > 0) {
IERC20(currency).safeTransferFrom(transactionExecutor, address(this), amount);
IERC20(currency).safeIncreaseAllowance(approveTo, amount);
}
HUB.act(publicationActionParams);
}
// DEPRECATED:
function _publicCollect(
Types.PublicationActionParams calldata publicationActionParams,
address transactionExecutor
@@ -119,36 +267,20 @@ contract PublicActProxy {
HUB.act(publicationActionParams);
}
function _publicSharedRevenueCollect(
Types.PublicationActionParams calldata publicationActionParams,
address transactionExecutor
) internal {
address collectModule = COLLECT_PUBLICATION_ACTION
.getCollectData(
publicationActionParams.publicationActedProfileId,
publicationActionParams.publicationActedId
)
.collectModule;
// View functions
BaseProfilePublicationData memory collectData = IBaseFeeCollectModule(collectModule).getBasePublicationData(
publicationActionParams.publicationActedProfileId,
publicationActionParams.publicationActedId
);
if (collectData.amount > 0) {
IERC20(collectData.currency).safeTransferFrom(transactionExecutor, address(this), collectData.amount);
IERC20(collectData.currency).safeIncreaseAllowance(collectModule, collectData.amount);
} else {
(address currency, uint256 amount) = IProtocolSharedRevenueMinFeeMintModule(collectModule)
.getMintFeeParams();
IERC20(currency).safeTransferFrom(transactionExecutor, address(this), amount);
IERC20(currency).safeIncreaseAllowance(collectModule, amount);
}
HUB.act(publicationActionParams);
function nonces(address signer) public view returns (uint256) {
return _nonces[signer];
}
function name() external pure returns (string memory) {
/// @dev This function is used to invalidate signatures by incrementing the nonce
function incrementNonce(uint8 increment) external {
uint256 currentNonce = _nonces[msg.sender];
_nonces[msg.sender] = currentNonce + increment;
emit Events.NonceUpdated(msg.sender, currentNonce + increment, block.timestamp);
}
function name() public pure returns (string memory) {
return 'PublicActProxy';
}
}

View File

@@ -218,320 +218,321 @@ contract PublicActProxyTest is BaseTest {
assertTrue(collectNFT.balanceOf(nftRecipient) > 0, 'NFT recipient balance is 0');
}
function testCanPublicSharedRevenueCollectPaid() public {
vm.prank(deployer);
address revenueShareModule = address(
new ProtocolSharedRevenueMinFeeMintModule(
address(hub),
address(collectPublicationAction),
address(moduleRegistry),
address(this)
)
);
// TODO: Move these to the PublicSharedRevenue module tests and add the PublicPaidAct tests
// function testCanPublicSharedRevenueCollectPaid() public {
// vm.prank(deployer);
// address revenueShareModule = addreeeess(
// new ProtocolSharedRevenueMinFeeMintModule(
// address(hub),
// address(collectPublicationAction),
// address(moduleRegistry),
// address(this)
// )
// );
collectPublicationAction.registerCollectModule(revenueShareModule);
// collectPublicationAction.registerCollectModule(revenueShareModule);
MockCurrency currency = new MockCurrency();
currency.mint(payer, 10 ether);
// MockCurrency currency = new MockCurrency();
// currency.mint(payer, 10 ether);
ProtocolSharedRevenueMinFeeMintModuleInitData memory exampleInitData;
exampleInitData.amount = 1 ether;
exampleInitData.collectLimit = 0;
exampleInitData.currency = address(currency);
exampleInitData.referralFee = 0;
exampleInitData.followerOnly = false;
exampleInitData.endTimestamp = 0;
exampleInitData.recipient = defaultAccount.owner;
exampleInitData.creatorClient = address(0);
// ProtocolSharedRevenueMinFeeMintModuleInitData memory exampleInitData;
// exampleInitData.amount = 1 ether;
// exampleInitData.collectLimit = 0;
// exampleInitData.currency = address(currency);
// exampleInitData.referralFee = 0;
// exampleInitData.followerOnly = false;
// exampleInitData.endTimestamp = 0;
// exampleInitData.recipient = defaultAccount.owner;
// exampleInitData.creatorClient = address(0);
Types.PostParams memory postParams = _getDefaultPostParams();
postParams.actionModules[0] = address(collectPublicationAction);
postParams.actionModulesInitDatas[0] = abi.encode(revenueShareModule, abi.encode(exampleInitData));
// Types.PostParams memory postParams = _getDefaultPostParams();
// postParams.actionModules[0] = address(collectPublicationAction);
// postParams.actionModulesInitDatas[0] = abi.encode(revenueShareModule, abi.encode(exampleInitData));
vm.prank(defaultAccount.owner);
defaultPubId = hub.post(postParams);
// vm.prank(defaultAccount.owner);
// defaultPubId = hub.post(postParams);
collectActionParams = Types.PublicationActionParams({
publicationActedProfileId: defaultAccount.profileId,
publicationActedId: defaultPubId,
actorProfileId: publicProfile.profileId,
referrerProfileIds: _emptyUint256Array(),
referrerPubIds: _emptyUint256Array(),
actionModuleAddress: address(collectPublicationAction),
actionModuleData: abi.encode(nftRecipient, abi.encode(currency, exampleInitData.amount, address(0)))
});
// collectActionParams = Types.PublicationActionParams({
// publicationActedProfileId: defaultAccount.profileId,
// publicationActedId: defaultPubId,
// actorProfileId: publicProfile.profileId,
// referrerProfileIds: _emptyUint256Array(),
// referrerPubIds: _emptyUint256Array(),
// actionModuleAddress: address(collectPublicationAction),
// actionModuleData: abi.encode(nftRecipient, abi.encode(currency, exampleInitData.amount, address(0)))
// });
vm.startPrank(payer);
currency.approve(address(publicActProxy), exampleInitData.amount);
publicActProxy.publicSharedRevenueCollect(collectActionParams);
vm.stopPrank();
// vm.startPrank(payer);
// currency.approve(address(publicActProxy), exampleInitData.amount);
// publicActProxy.publicSharedRevenueCollect(collectActionParams);
// vm.stopPrank();
CollectNFT collectNFT = CollectNFT(
CollectPublicationAction(collectPublicationAction)
.getCollectData(defaultAccount.profileId, defaultPubId)
.collectNFT
);
// CollectNFT collectNFT = CollectNFT(
// CollectPublicationAction(collectPublicationAction)
// .getCollectData(defaultAccount.profileId, defaultPubId)
// .collectNFT
// );
assertTrue(collectNFT.balanceOf(nftRecipient) > 0, 'NFT recipient balance is 0');
}
// assertTrue(collectNFT.balanceOf(nftRecipient) > 0, 'NFT recipient balance is 0');
// }
function testCanPublicSharedRevenueCollectPaidWithSig() public {
vm.prank(deployer);
address revenueShareModule = address(
new ProtocolSharedRevenueMinFeeMintModule(
address(hub),
address(collectPublicationAction),
address(moduleRegistry),
address(this)
)
);
// function testCanPublicSharedRevenueCollectPaidWithSig() public {
// vm.prank(deployer);
// address revenueShareModule = address(
// new ProtocolSharedRevenueMinFeeMintModule(
// address(hub),
// address(collectPublicationAction),
// address(moduleRegistry),
// address(this)
// )
// );
collectPublicationAction.registerCollectModule(revenueShareModule);
// collectPublicationAction.registerCollectModule(revenueShareModule);
MockCurrency currency = new MockCurrency();
currency.mint(payer, 10 ether);
// MockCurrency currency = new MockCurrency();
// currency.mint(payer, 10 ether);
ProtocolSharedRevenueMinFeeMintModuleInitData memory exampleInitData;
exampleInitData.amount = 1 ether;
exampleInitData.collectLimit = 0;
exampleInitData.currency = address(currency);
exampleInitData.referralFee = 0;
exampleInitData.followerOnly = false;
exampleInitData.endTimestamp = 0;
exampleInitData.recipient = defaultAccount.owner;
exampleInitData.creatorClient = address(0);
// ProtocolSharedRevenueMinFeeMintModuleInitData memory exampleInitData;
// exampleInitData.amount = 1 ether;
// exampleInitData.collectLimit = 0;
// exampleInitData.currency = address(currency);
// exampleInitData.referralFee = 0;
// exampleInitData.followerOnly = false;
// exampleInitData.endTimestamp = 0;
// exampleInitData.recipient = defaultAccount.owner;
// exampleInitData.creatorClient = address(0);
Types.PostParams memory postParams = _getDefaultPostParams();
postParams.actionModules[0] = address(collectPublicationAction);
postParams.actionModulesInitDatas[0] = abi.encode(revenueShareModule, abi.encode(exampleInitData));
// Types.PostParams memory postParams = _getDefaultPostParams();
// postParams.actionModules[0] = address(collectPublicationAction);
// postParams.actionModulesInitDatas[0] = abi.encode(revenueShareModule, abi.encode(exampleInitData));
vm.prank(defaultAccount.owner);
defaultPubId = hub.post(postParams);
// vm.prank(defaultAccount.owner);
// defaultPubId = hub.post(postParams);
collectActionParams = Types.PublicationActionParams({
publicationActedProfileId: defaultAccount.profileId,
publicationActedId: defaultPubId,
actorProfileId: publicProfile.profileId,
referrerProfileIds: _emptyUint256Array(),
referrerPubIds: _emptyUint256Array(),
actionModuleAddress: address(collectPublicationAction),
actionModuleData: abi.encode(nftRecipient, abi.encode(currency, exampleInitData.amount, address(0)))
});
// collectActionParams = Types.PublicationActionParams({
// publicationActedProfileId: defaultAccount.profileId,
// publicationActedId: defaultPubId,
// actorProfileId: publicProfile.profileId,
// referrerProfileIds: _emptyUint256Array(),
// referrerPubIds: _emptyUint256Array(),
// actionModuleAddress: address(collectPublicationAction),
// actionModuleData: abi.encode(nftRecipient, abi.encode(currency, exampleInitData.amount, address(0)))
// });
vm.prank(payer);
currency.approve(address(publicActProxy), exampleInitData.amount);
// vm.prank(payer);
// currency.approve(address(publicActProxy), exampleInitData.amount);
domainSeparator = keccak256(
abi.encode(
Typehash.EIP712_DOMAIN,
keccak256('PublicActProxy'),
MetaTxLib.EIP712_DOMAIN_VERSION_HASH,
block.chainid,
address(publicActProxy)
)
);
// domainSeparator = keccak256(
// abi.encode(
// Typehash.EIP712_DOMAIN,
// keccak256('PublicActProxy'),
// MetaTxLib.EIP712_DOMAIN_VERSION_HASH,
// block.chainid,
// address(publicActProxy)
// )
// );
publicActProxy.publicSharedRevenueCollectWithSig({
publicationActionParams: collectActionParams,
signature: _getSigStruct({
pKey: payerPk,
digest: _getActTypedDataHash(collectActionParams, publicActProxy.nonces(payer), type(uint256).max),
deadline: type(uint256).max
})
});
// publicActProxy.publicSharedRevenueCollectWithSig({
// publicationActionParams: collectActionParams,
// signature: _getSigStruct({
// pKey: payerPk,
// digest: _getActTypedDataHash(collectActionParams, publicActProxy.nonces(payer), type(uint256).max),
// deadline: type(uint256).max
// })
// });
CollectNFT collectNFT = CollectNFT(
CollectPublicationAction(collectPublicationAction)
.getCollectData(defaultAccount.profileId, defaultPubId)
.collectNFT
);
// CollectNFT collectNFT = CollectNFT(
// CollectPublicationAction(collectPublicationAction)
// .getCollectData(defaultAccount.profileId, defaultPubId)
// .collectNFT
// );
assertTrue(collectNFT.balanceOf(nftRecipient) > 0, 'NFT recipient balance is 0');
}
// assertTrue(collectNFT.balanceOf(nftRecipient) > 0, 'NFT recipient balance is 0');
// }
function testCanPublicSharedRevenueCollectFree() public {
address creatorClient = makeAddr('CREATOR_CLIENT');
address executorClient = makeAddr('EXECUTOR_CLIENT');
// function testCanPublicSharedRevenueCollectFree() public {
// address creatorClient = makeAddr('CREATOR_CLIENT');
// address executorClient = makeAddr('EXECUTOR_CLIENT');
uint256 mintFee = 10 ether;
// uint256 mintFee = 10 ether;
vm.prank(deployer);
address revenueShareModule = address(
new ProtocolSharedRevenueMinFeeMintModule(
address(hub),
address(collectPublicationAction),
address(moduleRegistry),
address(this)
)
);
// vm.prank(deployer);
// address revenueShareModule = address(
// new ProtocolSharedRevenueMinFeeMintModule(
// address(hub),
// address(collectPublicationAction),
// address(moduleRegistry),
// address(this)
// )
// );
collectPublicationAction.registerCollectModule(revenueShareModule);
// collectPublicationAction.registerCollectModule(revenueShareModule);
MockCurrency currency = new MockCurrency();
currency.mint(payer, mintFee);
// MockCurrency currency = new MockCurrency();
// currency.mint(payer, mintFee);
ProtocolSharedRevenueMinFeeMintModule(revenueShareModule).setMintFeeParams(address(currency), mintFee);
ProtocolSharedRevenueMinFeeMintModule(revenueShareModule).setProtocolSharedRevenueDistribution(
ProtocolSharedRevenueDistribution({
creatorSplit: 5000,
protocolSplit: 2000,
creatorClientSplit: 1500,
executorClientSplit: 1500
})
);
// ProtocolSharedRevenueMinFeeMintModule(revenueShareModule).setMintFeeParams(address(currency), mintFee);
// ProtocolSharedRevenueMinFeeMintModule(revenueShareModule).setProtocolSharedRevenueDistribution(
// ProtocolSharedRevenueDistribution({
// creatorSplit: 5000,
// protocolSplit: 2000,
// creatorClientSplit: 1500,
// executorClientSplit: 1500
// })
// );
ProtocolSharedRevenueMinFeeMintModuleInitData memory exampleInitData;
exampleInitData.amount = 0 ether;
exampleInitData.collectLimit = 0;
exampleInitData.currency = address(0);
exampleInitData.referralFee = 0;
exampleInitData.followerOnly = false;
exampleInitData.endTimestamp = 0;
exampleInitData.recipient = defaultAccount.owner;
exampleInitData.creatorClient = creatorClient;
// ProtocolSharedRevenueMinFeeMintModuleInitData memory exampleInitData;
// exampleInitData.amount = 0 ether;
// exampleInitData.collectLimit = 0;
// exampleInitData.currency = address(0);
// exampleInitData.referralFee = 0;
// exampleInitData.followerOnly = false;
// exampleInitData.endTimestamp = 0;
// exampleInitData.recipient = defaultAccount.owner;
// exampleInitData.creatorClient = creatorClient;
Types.PostParams memory postParams = _getDefaultPostParams();
postParams.actionModules[0] = address(collectPublicationAction);
postParams.actionModulesInitDatas[0] = abi.encode(revenueShareModule, abi.encode(exampleInitData));
// Types.PostParams memory postParams = _getDefaultPostParams();
// postParams.actionModules[0] = address(collectPublicationAction);
// postParams.actionModulesInitDatas[0] = abi.encode(revenueShareModule, abi.encode(exampleInitData));
vm.prank(defaultAccount.owner);
defaultPubId = hub.post(postParams);
// vm.prank(defaultAccount.owner);
// defaultPubId = hub.post(postParams);
collectActionParams = Types.PublicationActionParams({
publicationActedProfileId: defaultAccount.profileId,
publicationActedId: defaultPubId,
actorProfileId: publicProfile.profileId,
referrerProfileIds: _emptyUint256Array(),
referrerPubIds: _emptyUint256Array(),
actionModuleAddress: address(collectPublicationAction),
actionModuleData: abi.encode(
nftRecipient,
abi.encode(exampleInitData.currency, exampleInitData.amount, executorClient)
)
});
// collectActionParams = Types.PublicationActionParams({
// publicationActedProfileId: defaultAccount.profileId,
// publicationActedId: defaultPubId,
// actorProfileId: publicProfile.profileId,
// referrerProfileIds: _emptyUint256Array(),
// referrerPubIds: _emptyUint256Array(),
// actionModuleAddress: address(collectPublicationAction),
// actionModuleData: abi.encode(
// nftRecipient,
// abi.encode(exampleInitData.currency, exampleInitData.amount, executorClient)
// )
// });
vm.startPrank(payer);
currency.approve(address(publicActProxy), mintFee);
publicActProxy.publicSharedRevenueCollect(collectActionParams);
vm.stopPrank();
// vm.startPrank(payer);
// currency.approve(address(publicActProxy), mintFee);
// publicActProxy.publicSharedRevenueCollect(collectActionParams);
// vm.stopPrank();
CollectNFT collectNFT = CollectNFT(
CollectPublicationAction(collectPublicationAction)
.getCollectData(defaultAccount.profileId, defaultPubId)
.collectNFT
);
// CollectNFT collectNFT = CollectNFT(
// CollectPublicationAction(collectPublicationAction)
// .getCollectData(defaultAccount.profileId, defaultPubId)
// .collectNFT
// );
assertTrue(collectNFT.balanceOf(nftRecipient) > 0, 'NFT recipient balance is 0');
// assertTrue(collectNFT.balanceOf(nftRecipient) > 0, 'NFT recipient balance is 0');
assertEq(currency.balanceOf(defaultAccount.owner), (mintFee * 5000) / 10000, 'Creator balance is incorrect');
assertEq(
currency.balanceOf(hub.getTreasury()),
(mintFee * 2000) / 10000,
'Protocol treasury client balance is incorrect'
);
assertEq(currency.balanceOf(creatorClient), (mintFee * 1500) / 10000, 'Creator client balance is incorrect');
assertEq(currency.balanceOf(executorClient), (mintFee * 1500) / 10000, 'Executor client balance is incorrect');
}
// assertEq(currency.balanceOf(defaultAccount.owner), (mintFee * 5000) / 10000, 'Creator balance is incorrect');
// assertEq(
// currency.balanceOf(hub.getTreasury()),
// (mintFee * 2000) / 10000,
// 'Protocol treasury client balance is incorrect'
// );
// assertEq(currency.balanceOf(creatorClient), (mintFee * 1500) / 10000, 'Creator client balance is incorrect');
// assertEq(currency.balanceOf(executorClient), (mintFee * 1500) / 10000, 'Executor client balance is incorrect');
// }
function testCanPublicSharedRevenueCollectFreeWithSig() public {
address creatorClient = makeAddr('CREATOR_CLIENT');
address executorClient = makeAddr('EXECUTOR_CLIENT');
// function testCanPublicSharedRevenueCollectFreeWithSig() public {
// address creatorClient = makeAddr('CREATOR_CLIENT');
// address executorClient = makeAddr('EXECUTOR_CLIENT');
uint256 mintFee = 10 ether;
// uint256 mintFee = 10 ether;
vm.prank(deployer);
address revenueShareModule = address(
new ProtocolSharedRevenueMinFeeMintModule(
address(hub),
address(collectPublicationAction),
address(moduleRegistry),
address(this)
)
);
// vm.prank(deployer);
// address revenueShareModule = address(
// new ProtocolSharedRevenueMinFeeMintModule(
// address(hub),
// address(collectPublicationAction),
// address(moduleRegistry),
// address(this)
// )
// );
collectPublicationAction.registerCollectModule(revenueShareModule);
// collectPublicationAction.registerCollectModule(revenueShareModule);
MockCurrency currency = new MockCurrency();
currency.mint(payer, mintFee);
// MockCurrency currency = new MockCurrency();
// currency.mint(payer, mintFee);
ProtocolSharedRevenueMinFeeMintModule(revenueShareModule).setMintFeeParams(address(currency), mintFee);
ProtocolSharedRevenueMinFeeMintModule(revenueShareModule).setProtocolSharedRevenueDistribution(
ProtocolSharedRevenueDistribution({
creatorSplit: 5000,
protocolSplit: 2000,
creatorClientSplit: 1500,
executorClientSplit: 1500
})
);
// ProtocolSharedRevenueMinFeeMintModule(revenueShareModule).setMintFeeParams(address(currency), mintFee);
// ProtocolSharedRevenueMinFeeMintModule(revenueShareModule).setProtocolSharedRevenueDistribution(
// ProtocolSharedRevenueDistribution({
// creatorSplit: 5000,
// protocolSplit: 2000,
// creatorClientSplit: 1500,
// executorClientSplit: 1500
// })
// );
ProtocolSharedRevenueMinFeeMintModuleInitData memory exampleInitData;
exampleInitData.amount = 0 ether;
exampleInitData.collectLimit = 0;
exampleInitData.currency = address(0);
exampleInitData.referralFee = 0;
exampleInitData.followerOnly = false;
exampleInitData.endTimestamp = 0;
exampleInitData.recipient = defaultAccount.owner;
exampleInitData.creatorClient = creatorClient;
// ProtocolSharedRevenueMinFeeMintModuleInitData memory exampleInitData;
// exampleInitData.amount = 0 ether;
// exampleInitData.collectLimit = 0;
// exampleInitData.currency = address(0);
// exampleInitData.referralFee = 0;
// exampleInitData.followerOnly = false;
// exampleInitData.endTimestamp = 0;
// exampleInitData.recipient = defaultAccount.owner;
// exampleInitData.creatorClient = creatorClient;
Types.PostParams memory postParams = _getDefaultPostParams();
postParams.actionModules[0] = address(collectPublicationAction);
postParams.actionModulesInitDatas[0] = abi.encode(revenueShareModule, abi.encode(exampleInitData));
// Types.PostParams memory postParams = _getDefaultPostParams();
// postParams.actionModules[0] = address(collectPublicationAction);
// postParams.actionModulesInitDatas[0] = abi.encode(revenueShareModule, abi.encode(exampleInitData));
vm.prank(defaultAccount.owner);
defaultPubId = hub.post(postParams);
// vm.prank(defaultAccount.owner);
// defaultPubId = hub.post(postParams);
collectActionParams = Types.PublicationActionParams({
publicationActedProfileId: defaultAccount.profileId,
publicationActedId: defaultPubId,
actorProfileId: publicProfile.profileId,
referrerProfileIds: _emptyUint256Array(),
referrerPubIds: _emptyUint256Array(),
actionModuleAddress: address(collectPublicationAction),
actionModuleData: abi.encode(
nftRecipient,
abi.encode(exampleInitData.currency, exampleInitData.amount, executorClient)
)
});
// collectActionParams = Types.PublicationActionParams({
// publicationActedProfileId: defaultAccount.profileId,
// publicationActedId: defaultPubId,
// actorProfileId: publicProfile.profileId,
// referrerProfileIds: _emptyUint256Array(),
// referrerPubIds: _emptyUint256Array(),
// actionModuleAddress: address(collectPublicationAction),
// actionModuleData: abi.encode(
// nftRecipient,
// abi.encode(exampleInitData.currency, exampleInitData.amount, executorClient)
// )
// });
vm.startPrank(payer);
currency.approve(address(publicActProxy), mintFee);
vm.stopPrank();
// vm.startPrank(payer);
// currency.approve(address(publicActProxy), mintFee);
// vm.stopPrank();
domainSeparator = keccak256(
abi.encode(
Typehash.EIP712_DOMAIN,
keccak256('PublicActProxy'),
MetaTxLib.EIP712_DOMAIN_VERSION_HASH,
block.chainid,
address(publicActProxy)
)
);
// domainSeparator = keccak256(
// abi.encode(
// Typehash.EIP712_DOMAIN,
// keccak256('PublicActProxy'),
// MetaTxLib.EIP712_DOMAIN_VERSION_HASH,
// block.chainid,
// address(publicActProxy)
// )
// );
publicActProxy.publicSharedRevenueCollectWithSig({
publicationActionParams: collectActionParams,
signature: _getSigStruct({
pKey: payerPk,
digest: _getActTypedDataHash(collectActionParams, publicActProxy.nonces(payer), type(uint256).max),
deadline: type(uint256).max
})
});
// publicActProxy.publicSharedRevenueCollectWithSig({
// publicationActionParams: collectActionParams,
// signature: _getSigStruct({
// pKey: payerPk,
// digest: _getActTypedDataHash(collectActionParams, publicActProxy.nonces(payer), type(uint256).max),
// deadline: type(uint256).max
// })
// });
CollectNFT collectNFT = CollectNFT(
CollectPublicationAction(collectPublicationAction)
.getCollectData(defaultAccount.profileId, defaultPubId)
.collectNFT
);
// CollectNFT collectNFT = CollectNFT(
// CollectPublicationAction(collectPublicationAction)
// .getCollectData(defaultAccount.profileId, defaultPubId)
// .collectNFT
// );
assertTrue(collectNFT.balanceOf(nftRecipient) > 0, 'NFT recipient balance is 0');
// assertTrue(collectNFT.balanceOf(nftRecipient) > 0, 'NFT recipient balance is 0');
assertEq(currency.balanceOf(defaultAccount.owner), (mintFee * 5000) / 10000, 'Creator balance is incorrect');
assertEq(
currency.balanceOf(hub.getTreasury()),
(mintFee * 2000) / 10000,
'Protocol treasury client balance is incorrect'
);
assertEq(currency.balanceOf(creatorClient), (mintFee * 1500) / 10000, 'Creator client balance is incorrect');
assertEq(currency.balanceOf(executorClient), (mintFee * 1500) / 10000, 'Executor client balance is incorrect');
}
// assertEq(currency.balanceOf(defaultAccount.owner), (mintFee * 5000) / 10000, 'Creator balance is incorrect');
// assertEq(
// currency.balanceOf(hub.getTreasury()),
// (mintFee * 2000) / 10000,
// 'Protocol treasury client balance is incorrect'
// );
// assertEq(currency.balanceOf(creatorClient), (mintFee * 1500) / 10000, 'Creator client balance is incorrect');
// assertEq(currency.balanceOf(executorClient), (mintFee * 1500) / 10000, 'Executor client balance is incorrect');
// }
}